I'm building a search component in a ReactJs application sitting on top of a headless WordPress CMS and I've run into a problem which I can't seem to fix. It might be that I'm doing something obviously wrong - I'm new to this aspect of WordPress.
I'm trying to query a specific custom post type: "maritimeimagearchive". "maritimeimagearchive" has a number of custom fields attached to it, one of which is "accepted_image_type". "accepted_image_type" has a number of potential values but to keep things simple I've limited it to "print" and "glass-plate" for testing purposes.
If I hit the rest api endpoint with the following request, all works fine: http://localhost:10058/wp-json/rmg/v1/search/?s=manchester
However, if I hit the rest api endpoint with either http://localhost:10058/wp-json/rmg/v1/search/?accepted_image_type=print or http://localhost:10058/wp-json/rmg/v1/search/?accepted_image_type=glass-plate, the returned dataset contains all posts with an "accepted_image_type" of "print" or "glass-plate".
There are other posts with different "accepted_image_type" values which I've left in for a sanity check and it's not returning those (that would be genuinely weird). But I'm stuck as to what I'm doing wrong. I've checked in Local by Flywheel's wordpress database and the data is in there stored as strings (not arrays or serialised).
Here's the full code for the custom route - I'm using Postman to test it. Can anyone give me an idea of what I'm doing wrong?
The full code for the route is as follows:
<?php
add_action('rest_api_init', 'maritimeImageRoute');
function maritimeImageRoute () {
register_rest_route('rmg/v1','search', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'getMaritimeImages',
));
}
function getMaritimeImages ( $data ) {
$search_query = $data['s'];
$args = array(
'post_type' => 'maritimeimagearchive',
's' => $search_query,
'meta_query' => array(
array(
'key' => 'accepted_image_type',
'value' => array('print', 'glass-plate'),
'compare' => 'IN',
),
),
);
$query = new WP_Query($args);
$data = array();
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
// Get the accepted_image_type field value
$accepted_image_type = get_field('accepted_image_type');
$data[] = array(
'id' => get_the_ID(),
'slug' => get_post_field('post_name'),
'permalink' => get_the_permalink(),
'title' => get_the_title(),
'content' => get_the_content(),
'thumbnail' => get_the_post_thumbnail(),
'accepted_image_type' => $accepted_image_type,
);
}
}
wp_reset_postdata();
return $data;
}
?>
Thanks.
accepted_image_type
is being read in as a parameter, as far as I can tell it's hardcoded regardless of what gets put in the URL. Note thatmeta_query
has a big performance cost that increases as the site gets larger,accepted_image_type
would be significantly faster if it was a custom taxonomy with aprint
term and aglass-plate
term. Otherwise the reason it ignores theaccepted_image_type
URL parameter is because nothing is reading it in so why would it? Like how you don't paint a Monet when you wash your clothes, nobody told you to, you didn't knowshow_in_rest
set to true in your CPT registration you'd be able to do this entirely from thewp-json/wp/v2/maritimeimagearchive
endpoint with the parameters?s=XYZ&meta_key= accepted_image_type&meta_value=glass
or something to that effect, with a standardised WP post object with all that data returned. If your field plugin is registering your post meta fields with WP they may even show up without any additional code. WP itself also has a dedicated search endpoint if you want to search across post types