B.Doe B.Doe - 3 months ago 48
PHP Question

Wordpress pre_get_posts filtering with advanced custom fields

I just can't find answer nor I can find related articles for my specific cases (or I found but didn't recognize it).

So, I have normal blog posts, and I have custom field name "tag" where I have only 1 word "music" (tag is text type).

My php for selecting all posts which have "music" in "tag" is:

add_filter('query_vars', function( $vars ) {
$vars[] = 'tag';

return $vars;
});


add_action( 'pre_get_posts', function ( $query ) {
if (!empty($_GET)) {

if ($tag = get_query_var('tag', false)) {
$meta_query[] = array(
'key' => 'tag',
'value' => $tag,
'compare' => '='
);
}

$query->query_vars['meta_query'] = $meta_query;
}
}, 1);


Now, when I type in url for example: localhost/myblog/?tag=music none of posts are showing, even tho I have few posts with "music" in "tag" field.
I would like to get solution for this simple case first, cause i duno what im doing wrong.

Also, I would like solution if I want to make multiple value in text field "tag" for example: "music, film, pop, life" so when people type in search "life film" they get all posts with those specific fields. Thank you and sorry for bigger wall of text than expected. Any help will be appriciated.

Answer

As I understand from your explanation, "tag" is just a custom field, not taxonomy. So you don't need to check any query var, just use "meta query" and that's all.

add_action('pre_get_posts', 'make_my_query');

function make_my_query($query) {
  if (!is_admin() && !empty($_GET) && isset($_GET['tag']) && $query->is_main_query()) {
    $query->set('meta_query', array( array(
      'key' => 'tag',
      'value' => sanitize_text_field($_GET['tag'])
    ) ) );
  }
}

If you use this snippet, main query on page will contain only posts with custom field key "tag" and value from $_GET. I've added some checks, to be sure that we're not viewing admin panel and modified query is main query on page. Otherwise it may be some mess. Also I sanitized GET value.

Now, your second question. It's possible, but we need to modify our snippet. First of all, let's decide, how will people ask for multiple tags? I prefer using commas. So url will look like that: localhost/myblog/?tag=music,film. Now let's send it to WP query:

add_action('pre_get_posts', 'make_my_query');

function make_my_query($query) {
  if (!is_admin() && !empty($_GET) && isset($_GET['tag'] && $query->is_main_query()) {
    $get_params = explode(',', $_GET['tag']);
    $meta_query = array(
      'relation' => 'OR'
    );
    foreach ($get_params as $param) {
      $meta_query[] = array(
        'key' => 'tag',
        'value' => sanitize_text_field($param)
      );
    }
    $query->set('meta_query', $meta_query);
  }
}

That's all. Now people, asking for posts with "?tag=film,music" will see posts that have "film" or "music" value of "tag" field. If you want to show posts, that only have all asked tags, change "relation" from "OR" to "AND". Hope that helps!