0

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.

3
  • I can't see in your code where 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 that meta_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 a print term and a glass-plate term. Otherwise the reason it ignores the accepted_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 know
    – Tom J Nowell
    Commented Mar 1, 2023 at 10:34
  • Like I say, new to this - knew it would be something obvious. Thanks for that and also the heads up re. meta_query. If you put it in full answer format,. I'll mark it as accepted. Cheers. It's working now.
    – Stef
    Commented Mar 1, 2023 at 12:20
  • as an aside, with show_in_rest set to true in your CPT registration you'd be able to do this entirely from the wp-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
    – Tom J Nowell
    Commented Mar 1, 2023 at 13:43

1 Answer 1

1

It isn't reading the acceptable image type parameter because there is no code to read it, and the acceptable image types have been hardcoded here:

            array(
                'key' => 'accepted_image_type',
                'value' => array('print', 'glass-plate'),
                'compare' => 'IN',
            ),

Much like you did here for the search parameter:

$search_query = $data['s'];

It needs to do the same for the acceptable image type parameter too.

Sidenotes:

  • Post meta is ultra fast when you already know the post, get_post_meta is blazingly fast for this reason because you have to give it a post ID. But, post meta is awful for searches, and the performance/scaling cost rises dramatically as the size of the post meta table increases. Instead either replace this field with a custom taxonomy, or store it in both so that you can get the performance benefits of replacing it with a tax_query
  • you can probably replace this endpoint with the default stock endpoints that come with WordPress. The URLs might not be as pretty due to the extra URL parameters but it would eliminate a bunch of code to maintain for free
1
  • Thanks again - it's an area of WordPress I'm just starting to get into so numerous gaps in my knowledge - I guess practice and lots of reading of documentation is the way to go.
    – Stef
    Commented Mar 1, 2023 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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