One of the nicest and most flexible aspects of the WordPress API is the ability to associate meta data with certain models – for lack of a better term – in the database.

That is, we can assign meta value to Users, Posts, Authors, and so on.

Retrieving the data is typically trivially easy. Simply supply the ID of the model in question and then pass the key value for said post meta.

But what if you need to get the post ID or post meta key by the meta value instead?

Get Post ID By Meta Value

Whenever you end up having to locate the post ID or the meta key by the value instead, it naturally feels like you’re doing something backwards. I think a case can be made for either misusing the API and/or not properly organizing your data.

Nonetheless, there have been projects where I’ve needed to retrieve either the post ID or the post’s meta key when all I had was the value.

An Actual Example

But before at looking at how to do it, there needs to be some sort of example data:

Let’s say, for example, that I have a page that has an associated post meta value of “This page is locked.”

Because the database is large, I don’t know the page’s ID nor do I know the meta key that is associated with the set piece of meta data.

So here’s what I have:

  • It’s a page post type
  • The meta value is “This page is locked.”

There are two ways that we can go about actually retrieving this information.

1. Using WP_Query and The Loop

The first way that you can retrieve a post’s ID through it’s meta value is by using WP_Query. The only information you really need to know is the meta value for which you’re looking, although it also helps to have the post type handy.

To do this, you can setup the following query:

$args = array(
	'post_type'		=>	'page',
	'meta_query'	=>	array(
		array(
			'value'	=>	'this is my example value.'
		)
	)
);
$my_query = new WP_Query( $args );

From here, you can setup a standard variation of The Loop:

if( $my_query->have_posts() ) {
  while( $my_query->have_posts() ) {
    $my_query->the_post();
    // Do your work...
  } // end while
} // end if
wp_reset_postdata();

But if you’re expecting a single post, then there’s no need to actually setup the while loop.

Finally, note that the more information you have about the post, the better. That is, knowing the post type is good, but knowing more meta information about the post can help provide a more optimized query.

2. Using SQL

On the other hand, there are times when it’s possible to use raw SQL to retrieve the results. To do this, you’ll need two pieces of information:

  • The name of the table in which the meta data is kept. In our case, that’s the wp_postmeta table
  • The post meta value

From here, you can use $wpdb and raw SQL for retrieving the results:

global $wpdb;
$results = $wpdb->get_results( "select post_id, meta_key from $wpdb->postmeta where meta_value = 'this is my example value.'", ARRAY_A );

That said, I don’t actually recommend doing this unless you’re extraordinarily skilled with SQL and have a deep understanding of query performance, the database schema indexes, etc.

Which is Better?

When it comes to writing code like this, I usually default to using the WordPress API – that is, WP_Query – for two reasons:

  1. It provides cleaner, more readable code within the context of a WordPress codebase
  2. It will ultimately be reduced to optimized SQL that’s better than what I could’ve come up with on my own

The two example above are simplistic. It’s not often that you’ll need to run a query to pull back one or two results by meta values, nor is it common that you’ll need a simple SELECT statement.

Instead, you’ll likely need more information in order to provide JOINS, LIMITS, and so on in order to make sure you’re pulling back exactly what you need.

So, with all of that said, I recommend using WP_Query – that’s what it’s there for – but if you’re dealing with a complicated set of data, and are deeply familiar with both the WordPress database scheme and SQL, then have it.