I've created a custom post, events, and saved the meta data event_year to each event. I'm trying to get a year's event archive. When I go the the following URL, the meta_key and meta_value are not set for some reason, and thus the event archive is unfiltered.


Debugging the values:

echo $wp_query->query_vars['post_type']; // 'events'
echo $wp_query->query_vars['meta_key']; // -blank-
echo $wp_query->query_vars['meta_value']; // -blank-

Why can't I set the meta_key and meta_value?

The meta_values are saved to the events. I've successfully displayed them:

get_post_meta($post->ID, 'event_year', true); // '2011'  

That's because 'meta_key' and 'meta_value' are not public query vars. In other words, you can't use them in URLs directly, nor should you.

Instead, register a specific query var, like so:

function register_my_qv() {
  global $wp;
  $wp->add_query_var( 'my_qv' );
add_action( 'init', 'register_my_qv' );

Then, you can go to a URL like this: ?my_qv=foobar

All you need to do now is map your query var to the actual query you want to do:

function map_my_qv( $wp_query ) {
  if ( $meta_value = $wp_query->get( 'my_qv' ) ) {
    $wp_query->set( 'meta_key', 'some_meta_key' );
    $wp_query->set( 'meta_value', $meta_value );
add_action( 'parse_query', 'map_my_qv' );
  • Okay. I was using the public URL as a test for a rewrite rule. Sorry for witholding my ultimate goal. I want to add this: add_rewrite_rule('^events/([0-9]+)$', 'index.php?post_type=events&meta_key=event_year&meta_value=$1'); Is this still not allowed?
    – Matt
    Jul 8 '11 at 0:09
  • 1
    I'm not sure. You'll just have to try it for yourself.
    – scribu
    Jul 8 '11 at 9:15

I can't add a comment to the scribu's excellent answer due to low reputation, but still the second part of the code (map_my_qv function) while working on WP 4.2 was giving me 404s, missing posts in admin and PHP notices about $meta_value variable not set. Therefore, here's the edited code:

function map_my_qv( $wp_query ) {
    if ( is_admin() || ! $wp_query->is_main_query() ) 

    if ( $wp_query->get( 'my_qv1' ) ) {
        $wp_query->set( 'meta_key', 'my_meta_key1' );
        $wp_query->set( 'meta_value', $wp_query->get( 'my_qv1' ) );
    if ( $wp_query->get( 'my_qv2' ) ) {
        $wp_query->set( 'meta_key', 'my_meta_key2' );
        $wp_query->set( 'meta_value', $wp_query->get( 'my_qv2' ) );
add_action( 'parse_query', 'map_my_qv' );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.