admin管理员组

文章数量:1416051

I'm looking to hook into pre_get_posts to alter WP_Query and put in a condition for the meta_query portion. I want my hook to be non-destructive to any other hook that may have modified this key.

What is the most appropriate way to determine if this key is set and, if it is, appropriately append to it an additional AND condition without compromising any prior modifications that may have been done by other plugins.

I'm looking to hook into pre_get_posts to alter WP_Query and put in a condition for the meta_query portion. I want my hook to be non-destructive to any other hook that may have modified this key.

What is the most appropriate way to determine if this key is set and, if it is, appropriately append to it an additional AND condition without compromising any prior modifications that may have been done by other plugins.

Share Improve this question asked Aug 12, 2019 at 17:04 Ryan GriffithRyan Griffith 1012 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

You can use the WP_Query::get method to get whatever is in the meta query like this:

add_action('pre_get_posts','add_another_meta_query');

function add_another_meta_query($query){
  //Be sure to only use the main query on frontend
  if($query->is_main_query() && !is_admin()){
    $meta_query = $query->get('meta_query',array());
    $new_meta_query = array();
    //now, $meta_query has the meta_query if set (or an array)
    //check if the old version of meta_query is used
    if($meta_key = $query->get('meta_key',NULL)){
       $old_type_of_meta = array();
       $old_type_of_meta['key'] = $meta_key;
       $query->unset('meta_key');
       if($meta_value = $query->get('meta_value',NULL)){
        $old_type_of_meta['value'] = $meta_value;
        $query->unset('meta_value');
       } elseif($meta_value = $query->get('meta_value_num',NULL)){
         $old_type_of_meta['value'] = $meta_value;
         $query->unset('meta_value_num');
       } else {
         $old_type_of_meta['compare'] = 'EXISTS';
       }
       if($meta_compare = $query->get('meta_compare',NULL)){
         $old_type_of_meta['compare'] = $meta_compare;
         $query->unset('meta_compare');
       }
       if($meta_type = $query->get('meta_type',NULL)){
        $old_type_of_meta['type'] = $meta_type;
        $query->unset('meta_type');
       }
       $new_meta_query[] = $old_type_of_meta;
       if($orderby = $query->get('orderby')){
         if(!is_array($orderby)){
            $orderby = str_replace(array('meta_value','meta_value_num'),array($meta_key,$meta_key),$orderby);
            $query->set('orderby',$orderby);
         }
       }
    }
    if(isset($meta_query['relation'])){
        //there is a special relation set within the meta_query.
        //to preserve this, we have to encapsulate the old meta queries
        $new_meta_query[] = $meta_query;
    } else {
       //there is no special relation set on global level ("AND" is used)
       //we can just merge them all together
       foreach($meta_query as $old_single_meta_query){
          $new_meta_query[] = $old_single_meta_query;
       }
    }
    //now we got all the "old" meta_queries in our $new_meta_query array.
    //let's add our own!
    $new_meta_query[] = array(
                        'key' => 'my_awesome_meta_key',
                        'value' => 'whatever_i_need',
                        'compare' => '=',
                        'type' => '',
                        );  
    //Last but not least: put it back into the $query
    $query->set('meta_query',$new_meta_query); 
  }
}

Happy Coding!

本文标签: wp queryAppending to existing WPQuery39s metaquery if exists