I’ve set up an ACF post type called “encyclopedia” with a taxonomy category called “topics.” I now want to create an Elementor search results page that will only show post types of “encyclopedia” with the category of “topic.” I’ve tried making a PHP filter to restrict results to that criteria, but it’s still showing all entries that contain the entered search term from across the entire site.
Below is the code to show any encyclopedia entries that meet the search criteria, but it’s showing all entries that contain the entered search criteria.
Any suggestions for what I need to do differently?
Thanks in advance for your help.
if (!is_admin()) {
function mv_search_filter($query) {
if ($query->is_search) {
$query->set('post_type', array( 'encyclopedia' ));
}
return $query;
}
add_filter('pre_get_posts','mv_search_filter');
}
Hi, i would like to sort all posts according to the date of my start_time meta field. But no matter what i try i always get Nothing Found. Also had no luck when i try get_posts or a WP_Query.
What am i doing wrong?
Here’s the code:
function mind_pre_get_posts( $query ) {
if( is_admin() ) {
return $query;
}
if( $query->is_main_query() ) {
$query->set('orderby', 'meta_value');
$query->set('meta_key', 'start_time');
$query->set('order', 'DESC');
}
return $query;
}
add_action('pre_get_posts', 'mind_pre_get_posts');
And here’s the custom field group:
acf_add_local_field_group(array(
'key' => 'group_1',
'title' => 'Meta info',
'fields' => array (
array (
'key' => 'start_time',
'label' => 'Exhibition start',
'name' => 'exhibition_start',
'type' => 'date_picker',
),
array (
'key' => 'end_time',
'label' => 'Exhibition end',
'name' => 'exhibition_end',
'type' => 'date_picker',
)
),
'location' => array (
array (
array (
'param' => 'post_type',
'operator' => '==',
'value' => 'post',
),
),
),
));
I’ve previously used CPTUI, and recently migrated my CPTs and Taxonomies to ACF.
In order to get CPTs to show up in my archives, I used to make a call to cptui_get_post_type_slugs()
, which no longer works since I’ve disabled CPTUI.
What’s the right way to get the CPT slugs from ACF?
Here’s the full source I was using to merge my CPTs with the “normal” archive post types:
function my_cptui_add_post_types_to_archives( $query ) {
// We do not want unintended consequences.
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( (is_category() || is_tag() ) && empty( $query->query_vars['suppress_filters'] ) ) {
$cptui_post_types = cptui_get_post_type_slugs();
$all_post_types = array_filter(array_merge( (array)get_query_var('post_type'), (array)$cptui_post_types ));
$post_type_filter = $_GET["post_type"];
if (!empty($post_type_filter) && in_array($post_type_filter, $all_post_types)) {
$query->set(
'post_type',
array ( $post_type_filter )
);
}
}
}
add_filter( 'pre_get_posts', 'my_cptui_add_post_types_to_archives' );
Hello
I have two custom post types (kurse, infoabend) with ACF date fields. The query of these posts sorted by date works fine.
$today = date ('Ymd');
$args = array(
'post_type' => array( 'kurse', 'infoabend' ),
'post_status' => array( 'publish', 'future' ),
'posts_per_page' => $posts_per_page,
'paged' => $paged,
'meta_query' => array(
'relation' => 'OR',
'kurs_clause' => array(
'key' => 'kurs_kursdaten_0_datum',
'compare' => '>=',
'value' => $today,
),
'infoabend_clause' => array(
'key' => 'datum',
'compare' => '>=',
'value' => $today,
),
),
'orderby' => array(
'kurs_clause' => $order,
'infoabend_clause' => $order,
),
);
I added ACF fields to the search and limited search to these two post types. To be able to sort the search results by date, I added the meta query I used in the first query.
add_action( 'pre_get_posts', __NAMESPACE__ . '\\d_edit_wp_query' );
function d_edit_wp_query( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_search ) {
if( !empty( $query->query['orderby'] ) && 'date' === $query->query['orderby'] {
$current_meta = ( empty ( $query->get('meta_query' ) ) )
? []
: $query->get( 'meta_query' );
$today = date ('Ymd');
$custom_meta = [
'relation' => 'OR',
'kurs_clause' => array(
'key' => 'kurs_kursdaten_0_datum',
'compare' => '>=',
'value' => $today,
'meta_type' => 'DATE',
),
'infoabend_clause' => array(
'key' => 'datum',
'compare' => '>=',
'value' => $today,
'meta_type' => 'DATE',
),
'orderby' => array(
'kurs_clause' => $query->query['order'],
'infoabend_clause' => $query->query['order'],
)
];
$meta_query = $current_meta[] = $custom_meta;
}
}
}
Unfortunately, the sorting by date does not work correctly. I would be grateful for any tips and ideas on how to solve the problem.
I have the following code for functions.php working for the post archives belonging to the whole taxes. It sorts their archive pages by date set in ACF field ‘release-date’.
add_action( 'pre_get_posts', 'customize_game_tag_archive_query', 10 );
function customize_game_tag_archive_query( $query ) {
if ( $query->is_tax( array ('time', 'game_status', 'genre', 'publisher', 'developer', 'platform', 'gameplay') ) ) {
// Sort posts by ACF release date.
$query->set( 'order', 'DESC' );
$query->set( 'orderby', 'meta_value_num' );
// ACF date field value is stored like 20220328 (YYYYMMDD).
$query->set( 'meta_key', 'release-date' );
}
}
It works fine, but I have a term ‘early-access’ inside ‘game_status’ tax and I need its archive to be sorted by another ACF date field named early-access-release-date
. How can I achieve this?
Hi – I would like to customize the main query in all locations to order by an ACF number field instead of by date. I don’t want any other modifications, just this. Am I on the right track with this?
function tas_album_query( $query ) {
if ( ! is_admin() && $query->is_main_query() ) {
// Not a query for an admin page.
// It's the main query for a front end page of your site.
if ( is_category() ) {
// It's the main query for a category archive.
// Let's change display order for the query for category archives.
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'tas_album_admin_acf_tas_album_order' );
$query->set( 'order', 'ASC' );
}
}
}
add_action( 'pre_get_posts', 'tas_album_query' );
Hi,
I have a custom post type called ‘reserveringen’. Inside this post type I have a custom field called ‘patient’ which is a object field to wordpress users. It returns a user_id. To show the user last_name in this post types admin columns I have this:
// Add custom admin columns
function columns_reserveringen($columns) {
unset($columns['date']);
$columns['achternaam'] = 'Achternaam';
$columns['voornaam'] = 'Voornaam';
$columns['status'] = 'Status';
$columns['datums'] = 'Datum';
return $columns;
}
add_filter('manage_reserveringen_posts_columns', 'columns_reserveringen');
// Make 'patient' column sortable
function make_patient_column_sortable($columns) {
$columns['achternaam'] = 'achternaam';
return $columns;
}
add_filter('manage_edit-reserveringen_sortable_columns', 'make_patient_column_sortable');
add_action( 'pre_get_posts', 'custom_patient_column_sorting' );
function custom_patient_column_sorting( $query ) {
if( ! is_admin() || ! $query->is_main_query() ) {
return;
}
if ( 'achternaam' === $query->get( 'orderby') ) {
$query->set( 'orderby', 'meta_value' );
$query->set( 'meta_key', 'patient' );
}
}
function display_posts_stickiness( $column, $post_id ) {
if ($column == 'achternaam') {
$patient = get_field('patient', $post_id);
$last_name = get_user_meta( $patient, 'last_name', true );
echo $last_name;
}
}
add_action( 'manage_posts_custom_column' , 'display_posts_stickiness', 10, 2 );
But now it doesn’t order by the user last_name field.
How can I manage that it does?
I’m working on a Woocommerce site that is integrated with a Store system. This system does not support regular Woocommerce variations so we used an ACF relationship field to create a custom variation selection on the frontend product page.
The client has requested that if products are variations only 1 of those should be displayed in the archive/category/search loop, so we need to exclude these extra products from the loop, but keep 1 of them.
What is the best way for me to do this?
My initial thought is looping through all products, create an array of product_ids that has values in the relationship field and 1 for the relationship values. array_diff those to only be left with extra varaitions. Then adding that array to post__not_in in pre_get_posts action.
Am I on the right track, I’m worried this might be too slow and wondering if there’s another speedy/optimal way to do this?
I’ve found all kinds of posts about how to create the PHP functions to achieve various results when outputting ACF data. I’ve had some success getting this to work with Gravity Forms. However, I am stumped on how to get the desired output in my pages (created with Elementor). I assume the php for various actions should be saved in functions.php. However, I’m not sure about the steps between the function(s) and the output on the page. Below is one of the uses I am working with.
I have a post archive called Staff Members Archive which pulls in the ACF posts for my Staff type. However, I am trying to sort the archive by Last Name (Ulitimately I want to sort by Department, Position, and Last Name).
My archive is pulling in the desired records from the Staff Member post type, but they are ordered by date.
I’ve included the following function below in my functions.php file. However, I’m not sure if this is even correct, or how to get it to apply to the Staff Members Archive. My post type is “Staff Members”.
I am working with Elementor and the loop/archive elements. Everything is working well except the sorting.
function sort_staff( $query ) {
// do not modify queries in the admin
if( is_admin() ) {
return $query;
}
// only modify queries for 'staff' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'Staff Member' ) {
$query->set('orderby', 'meta_value');
$query->set('meta_key', 'lname');
$query->set('order', 'ASC');
}
// return
return $query;
}
add_action('pre_get_posts', 'sort_staff');
If I was doing this in SQL, my query would be
SELECT * FROM Staff
WHERE active='Active'
ORDER BY FIELD(Department,'Admin','Fiscal', 'Maintenance'),
FIELD(Position, 'Manager', 'Supervisor', 'Staff'),
lname ASC;
Hello
I am stuck with the issue:
I have a loop section in my websites, where I want to show events. Elementor/Wordpress shows all post related on the publishing date. But I want to show the posts with the event-date (‘datum’). And only from today onwards. How can I manage that?
I tried also with the code:
function my_pre_get_posts( $query ) {
// do not modify queries in the admin
if ( is_admin() ) {
return $query;
}
// only modify queries for the main loop
if ( $query->is_main_query() ) {
// only modify queries on the events archive page
if ( is_post_type_archive( ‘events’ ) ) {
// Set meta query to filter by ‘datum’ field
$today = date( ‘Ymd’ ); // Format: YYYYMMDD
$meta_query = array(
array(
‘key’ => ‘datum’, // Replace with your ACF field name
‘value’ => $today,
‘compare’ => ‘>=’,
‘type’ => ‘DATE’,
),
);
$query->set( ‘post_type’, ‘events’ );
$query->set( ‘orderby’, ‘meta_value’ );
$query->set( ‘meta_key’, ‘datum’ ); // Replace with your ACF field name
$query->set( ‘order’, ‘ASC’ ); // Order: oldest date first
$query->set( ‘meta_query’, $meta_query );
}
}
// return
return $query;
}
add_action( ‘pre_get_posts’, ‘my_pre_get_posts’ );
Howdy!
I’ve tried to get this question answered in some other places, with no result… Now I hope some bright and kind mind here will help!
So: I am successfully using this functions.php snippet to exclude category 3 from the WordPress homepage:
function exclude_category_home( $query ) {
if ( $query->is_front_page ) {
$query->set( 'cat', '-3' );
}
return $query;
}
add_filter( 'pre_get_posts', 'exclude_category_home' );
A query (on a profile page tab by WPUM-plugin) for listing a users posts works fine:
$the_query = wpum_get_posts_for_profile( $data->user->ID );
But my homemade query on another profile page tab, for listing posts where the current_user-ID is the value of my ACF custom field “fetcher”:
$the_query = new WP_Query( array( 'meta_key' => 'fetcher', 'meta_value' => $user_ID ) );
…unintentionally excludes category 3, like on the frontpage (as soon as the snippet-filter is activated).
Why is that?
Hi, I’m trying to search a post which have a meta value that contains one of these values: 1408 or 1407. Within the postmeta table I have this:
a:3:{i:0;s:4:”1406″;i:1;s:4:”1407″;i:2;s:4:”1408″;}
So I’ve created a function which contains the following:
function add_related_posts_to_search( $query ) {
if( $query->is_search ) {
$search_term = $query->query_vars['s'];
$query->query_vars['s'] = '';
$post_ids = search_medici_in_servizio_title( $search_term );
if( ! empty( $post_ids ) ) {
$meta_query = array();
foreach($post_ids as $pi) {
$meta_query[] = array(
'key' => 'medici',
'value' => sprintf("'%s'", $pi),
'compare' => 'LIKE',
);
}
$query->set('meta_query', $meta_query);
}
}
}
add_action( 'pre_get_posts', 'add_related_posts_to_search' );
essentially I’m getting all the id of the posts that have the searched term (in this case is returned an array with 1407 and 1408), and then I’ve mounted a meta_query that should return all the posts that contains one of the values specified.
For some reason I doesn’t get any result, any idea?
I love the new Post Types function of ACF, i could stop use other plugins for it.
But the Taxonomies feature is little limited – even if you select e.g. Category taxonomy for a custom post type and you can then set this taxonomy for a post type, it does not mean the post does appear on the category page, unless you update wp_query, like this
add_filter('pre_get_posts', 'query_post_type');
function query_post_type($query) {
if( is_category() ) {
$post_type = get_query_var('post_type');
if($post_type)
$post_type = $post_type;
else
$post_type = array('nav_menu_item', 'post', 'movies'); // don't forget nav_menu_item to allow menus to work!
$query->set('post_type',$post_type);
return $query;
}
}
It would be great if users could just allow it in the ACF Post Type admin
I have the following code in my functions.php file which allows me to query posts in my custom post type named ‘jobs’ and filter them where an ACF field named ‘bracket’ matches a certain value. It works fine, but when the page loads and i see the url appended such as ‘/jobs/?bracket=20-30’ my wordpress navigation menu items aren’t present on the page. I can’t understand whats wrong?
Here is my functions.php code:
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query )
{
// bail early if is in admin
if( is_admin() )
{
return;
}
// get meta query
$meta_query = $query->get('meta_query');
// initialize meta query as empty array if not set
if ( ! is_array( $meta_query ) ) {
$meta_query = array();
}
// continue if not found in url
if( isset($_GET[ 'bracket' ]) )
{
// append meta query
$meta_query[] = array(
'key' => 'bracket',
'value' => $_GET['bracket'],
'compare' => '=',
);
}
// update meta query
$query->set('meta_query', $meta_query);
return;
}
Hello,
I’ve got two ACF fields I want to order.
1. True/False field “activi_datumperiode” (qw2)
2. Date field “activi_datum” (qw1)
I want the query to be ordered by qw2 first. All items with value 0 at the bottem (DESC).
Then I want all the dates qw1 be orderd ASC.
So it would be
– Post with date 01-01-2023
– Post with date 02-02-2023
– Post without date (value 0)
I can’t seem to fix this.. I think maybe because date field exists (empty) in every post so thats ASC the lowest. But can’t seem to figure this out.
Any clue whats wrong?
function custom_query_vars( $query ) {
if ( !is_admin() && $query->is_main_query() ) {
// advies only parents && alles geen paginatie
if ( is_post_type_archive() == 'activiteiten' ) {
$query->set( 'post_parent', 0 );
$query->set( 'posts_per_page', 20 );
$meta_query = array(
'relation' => 'OR',
'qw1' => array(
array(
'key' => 'activi_datum',
'value' => date('Ymd'),
'type' => 'DATE',
'compare' => '>='
),
array(
'key' => 'activi_datumperiode',
'value' => 1,
'compare' => '='
),
),
'qw2' => array(
'key' => 'activi_datumperiode',
'value' => 0,
'compare' => '='
),
);
$query->set( 'meta_query', $meta_query );
$query->set( 'orderby', array(
'qw2' => 'DESC',
'qw1' => 'ASC',
) );
//$query->set( 'order', 'ASC' );
}
}
return $query;
}
add_action( 'pre_get_posts', 'custom_query_vars' );
I’ve added a new “User field” in a CPT and wish to link the posts to specific users as I do not wish to change the author.
How would you go in order to display these relationships? I can get it working in making a repeater to show all of the authors posts. Don’t know where to start in order to display the User Field relationships…
The code i’m using to display the if usert = Author posts is the following.
<?php
function dynamic_ids_query( $query ) {
global $post;
global $current_user;
get_currentuserinfo();
$authorID = $current_user->ID;
if ( $query->query['post_type'][0] == 'taktiko-mitroo' or 'post' ) {
$query->set( 'author', $authorID );
}
}
add_action( 'pre_get_posts', 'dynamic_ids_query' );
?>
Any way to change it and make it to work for if user = user from the relationship?
Hello everybody,
I have an issue on a website.
I need to display movies (my custom post: ‘films’) and some have a release date (ACF field : ‘date_de_sortie’) and others do not have one.
I would like to display in first movies with release date (from the the closer to the further ) and only after, those which don’t have a release date (ordered by title).
For now it displays in first movies without a release date in and after those with a release date, order is ok.
Here is my function :
add_action( 'pre_get_posts', 'films_query' );
function films_query( $query ) {
if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
$cat_hide = get_field('categorie_des_films_a_masquer', 'options');
$taxquery = array(
array(
'taxonomy' => 'categorie_films',
'field' => 'term_id',
'terms' => $cat_hide,
'operator' => 'NOT IN',
)
);
$query->set( 'posts_per_page', '-1' );
$query->set( 'post_status', 'publish' );
$query->set( 'meta_key', 'date_de_sortie' );
$query->set( 'orderby', 'meta_value title' );
$query->set( 'order', 'ASC' );
$query->set( 'tax_query', $taxquery );
}
}
Do I need to use $query->set( ‘meta_query’, $meta_query ); with $meta_query args ?
Any help appreciated.
All the best.
Pierre
Hi,
I was reading the ACF guide on pre_get_posts at the end of the page.
That part works fine for me but I’m trying to get the soonest events first, but the old events still at the end.
Order by date ASC if the date is in the future
AND
Order by date DEC if the date is in the past
Example
1. Upcoming event – July 2022
2. Upcoming event – August 2022
3. Upcoming event – September 2022
4. Past event – June 2022
5. Past event – May 2022
6. Past event – April 2022
Is this possible with a single WP_Query?
Hello
I’d like to add some custom post types to the WP search results – however, some of those post types have a status field and the search results should be filtered by that – obviously some other post types e.g. ‘post’ do not have that status field – how can I do that – is there an easy way:
the following code is not working, or maybe works partially – hope somebody can get me going on this – thank you in advance for your help.
` function themeprefix_include_custom_post_types_in_search_results( $query ) {
if ( $query->is_main_query() && $query->is_search() && ! is_admin() ) {
$query->set( ‘post_type’, array( ‘post’, ‘cpt1’, ‘cpt2’, ‘cpt3’, ‘opportunity’ ) );
$query->set( ‘meta_query’, array(
‘relation’ => ‘OR’,
array(
‘key’ => ‘cpt1_status’,
‘value’ => ‘1’,
‘compare’ => ‘=’,
‘type’ => ‘NUMERIC’,
),
array(
‘key’ => ‘cpt2_status’,
‘value’ => ‘1’,
‘compare’ => ‘=’,
‘type’ => ‘NUMERIC’,
),
));
}
}
add_action( ‘pre_get_posts’, ‘themeprefix_include_custom_post_types_in_search_results’ );
In my ACF field group, which is set up for Post Type -> Product. I have added a new field property_reference
(Type = Text) to hold an individual reference number. I wanted to display this value in the Products table view for WooCommerce in my Admin WP Dashboard. So I have now created a custom column which outputs this value.
At the moment I only have three entries, these are BA001, BA002, BA003. However, before things get wild, I would like to be able to sort this custom column in order.
I have added some code shown below. This makes the Reference ID Column clickable, but provides ‘No products found’ line on the table.
So in order to make this sortable, to list in the order of the custom field property_reference
from highest to lowest. How do I set up the custom field and make use of the meta query?
I should note I’m a little new to this and still trying to get my head around it 🙂
Any help or advice would be much appreciated. Thanks
add_filter( 'manage_edit-product_sortable_columns', 'my_sortable_reference_column' );
function my_sortable_reference_column( $columns ) {
$columns['rm_reference'] = 'reference_id';
return $columns;
}
function product_rmreference_column_width_query( $query ) {
if ( is_admin() ) {
$orderby = $query->get( 'orderby' );
if ( 'reference_id' == $orderby ) {
$meta_query = array(
'relation' => 'OR',
array(
'key' => '_ref',
'compare' => '>',
'type' => 'NUMERIC'
),
array(
'key' => '_ref',
),
);
$query->set( 'meta_query', $meta_query );
$query->set( 'orderby', 'meta_value' );
}
}
}
add_action( 'pre_get_posts', 'product_rmreference_column_width_query' );
Hi,
i wanna set the post title from the value of two acf fields and I do it like the following (function great):
add_action( 'pre_get_posts', 'js_search_filter' );
function my_post_title_updater( $post_id ) {
if ( get_post_type() == 'video' ) {
$my_post = array();
$my_post['post_title'] = get_field( 'interpret_video', $post_id ) . ': ' . substr(get_field( 'titel_video', $post_id ), 0, 30) . '';
// Update the post into the database
wp_update_post( $my_post );
}
}
// run after ACF saves the $_POST['fields'] data
add_action('acf/save_post', 'my_post_title_updater', 20);
But now I wanna update the permalink of the now generatet title. How I gotta do this ?
How do you order a custom post type by Flexible Content custom field?
I have this code, but it doesn’t work with a Flexible Content custom field:
<?php
function my_pre_get_posts( $query ) {
// do not modify queries in the admin
if( is_admin() ) {
return $query;
}
// only modify queries for 'event' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'event' ) {
$query->set('orderby', 'meta_value');
$query->set('meta_key', 'start_date');
$query->set('order', 'ASC');
}
// return
return $query;
}
add_action('pre_get_posts', 'my_pre_get_posts');
?>
Hi
I would like to exclude posts with via the url based on a custom field and I followed this:
https://www.advancedcustomfields.com/resources/query-posts-custom-fields/
and “Dynamic $_GET parameters” which works but not if I want to exclude the post with the value.
I have a custom field called ‘members_only_video’ which is a True/False.
function my_pre_get_posts( $query ) {
// do not modify queries in the admin
if( is_admin() ) {
return $query;
}
// only modify queries for 'webinar' post type
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'webinar' ) {
// allow the url to alter the query
if( isset($_GET['members_only_video']) ) {
$query->set('meta_query', array(
array(
'key' => 'members_only_video',
'value' => $_GET['members_only_video'],
'compare' => '!=',
)));
}
}
// return
return $query;
}
add_action('pre_get_posts', 'my_pre_get_posts');
Hello,
I have a CPT and an ACF checkbox field called “coup_de_coeur”.
I’d like to display all the CPT posts when this checkbox is checked by the URL, like :
mywebsite.com/my-cpt?coup_de_coeur=VALUE (only one value is possible anyway)
I tried with this bit of code (I’m no expert, I checked several topics) but it doesn’t work, only get me a blank / error page.
Does someone has an idea please? 🙂
add_action('pre_get_posts', 'my_pre_get_posts');
function my_pre_get_posts( $query ) {
$meta_query = $query->get('meta_query');
if( isset($_GET['coup_de_coeur']) )
{
$meta_query[] = array(
'key' => 'coup_de_coeur',
'value' => $_GET['coup_de_coeur'],
'compare' => '=',
);
}
$query->set('meta_query', $meta_query);
return;
}
Hello and thanks for taking a look at this question.
I have been referring to this tutorial and code and having no luck.
I have a custom post type (gallery) which I need to allow site users to filter by several custom field values. So far I’m just trying to get one filter to work when entering URL directly in the browser. At one point I had the checkboxes working for a single value on the page (not sure how), but it never has worked for more than one filter or more than one value within a single field, and now it’s not working at all.
Though the URL updates properly, no filtering happens on the archive-gallery page. I’ve tried using the code in the tutorial, and the code attached below (they are different). I’ve tried changing the field I’m testing to a radio button instead of a checkbox, also with no success. I’ve also added $meta_query = [];” before “$meta_query = array(…” in the functions.php code below, otherwise I get a fatal error message when I try to filter anything.
Any help much appreciated!!
Here are all the specifics as I have them right now, just testing a single custom field :
Field key: field_6174a76da315c
Field name: type_of_art
Field type: radio button
Choices:
visual : Visual
literary : Literary
performing : Performing
other : Other
in mu-plugins I have set up the custom post type:
// Gallery post type
register_post_type('gallery', array(
'show_in_rest' => true,
'capability_type' => array('gallery item', 'gallery'),
'map_meta_cap' => true,
'supports' => array('title', 'editor', 'excerpt', 'thumbnail', 'revisions', 'custom-fields', 'author'),
'rewrite' => array('slug' => 'gallery'),
'has_archive' => true,
'public' => true,
'taxonomies' => array( 'post_tag', 'category' ),
'publicly_queryable' => true,
'labels' => array(
'name' => 'Gallery',
'add_new_item' => 'Add New Gallery Item',
'edit_item' => 'Edit Gallery Item',
'all_items' => 'Gallery',
'singular_name' => 'Gallery Item',
'show_in_rest' => true,
'exclude_from_search' => false,
),
'menu_icon' => 'dashicons-art'
));
in functions.php I have this:
// array of filters (field key => field name)
$GLOBALS['my_query_filters'] = array(
'field_6174a76da315c' => 'type_of_art'
// 'field_618edb3358d2c' => 'filter_test',
);
// action
add_action('pre_get_posts', 'my_pre_get_posts', 10, 1);
function my_pre_get_posts( $query ) {
// bail early if is in admin
if( is_admin() ) return;
// bail early if not main query
// - allows custom code / plugins to continue working
if( !$query->is_main_query() ) return;
// get meta query
$meta_query = $query->get('meta_query');
// loop over filters
foreach( $GLOBALS['my_query_filters'] as $key => $name ) {
// continue if not found in url
if( empty($_GET[ $name ]) ) {
continue;
}
// get the value for this filter
// eg: http://www.website.com/events?city=melbourne,sydney
$value = explode(',', $_GET[ $name ]);
// append meta query
$meta_query = [];
$meta_query[] = array(
'key' => $name,
'value' => $value,
'compare' => 'IN',
);
}
// update meta query
$query->set('meta_query', $meta_query);
And in my archive-gallery.php template file I have:
<div id="archive-filters">
<?php foreach( $GLOBALS['my_query_filters'] as $key => $name ):
// get the field's settings without attempting to load a value
$field = get_field_object($key, false, false);
// set value if available
if( isset($_GET[ $name ]) ) {
$field['value'] = explode(',', $_GET[ $name ]);
}
// create filter
?>
<div class="filter" data-filter="<?php echo $name; ?>">
<?php create_field( $field ); ?>
</div>
<?php endforeach; ?>
</div>
<script type="text/javascript">
(function($) {
// change
$('#archive-filters').on('change', 'input[type="checkbox"]', function(){
// vars
var url = '<?php echo home_url('gallery'); ?>';
args = {};
// loop over filters
$('#archive-filters .filter').each(function(){
// vars
var filter = $(this).data('filter'),
vals = [];
// find checked inputs
$(this).find('input:checked').each(function(){
vals.push( $(this).val() );
});
// append to args
args[ filter ] = vals.join(',');
});
// update url
url += '?';
// loop over args
$.each(args, function( name, value ){
url += name + '=' + value + '&';
});
// remove last &
url = url.slice(0, -1);
// reload page
window.location.replace( url );
});
})(jQuery);
</script>
</div>
Debug shows no errors with this code. When I put
localsite/gallery/?type_of_art=visual” in the browser, the archive page shows up with no posts filtered out.