• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Creating Site Meta Search In WordPress Multisite using Site Queries

Wordpress · August 5, 2022

WordPress is incredibly powerful, and every so often, a new feature gets added that goes under the radar that can dramatically change how you build sites. In WordPress 5.1, an addition of a new WP_Site_Query class was created. It allows you to query your network of sites but goes beyond just getting IDs and making you loop over them to use with switch_to_blog($id)

Here is another super-specific use case I had with WordPress Multisite recently.

I have a network comprised of thousands of sites. Each site has an options page that uses Advanced Custom Fields Pro. The information is things like the site’s name, country, etc.

I needed to implement a search that allowed me to query one or more of these meta fields. In my situation, each site belongs to a continent, country, state/region, local government area or city/town. I needed to retrieve a list of these sites based on a search keyword.

Here is how I did it.

First, I created a custom REST endpoint.

add_action( 'rest_api_init', function () {

    register_rest_route( 'utilities/v1', '/sites/search/(?P<search>([a-zA-Z]|%20)+)', array(
        'methods' => 'GET',
        'callback' => 'rest_search_sites',
        'permission_callback' => '__return_true'
    ) );
  
});

A pretty standard REST API route. Take note of how we create our parameter regex, though. We want to allow letters but also allow spaces as well. If someone types “United States of America,” it can see the whole term.

And here is the callback function for our route.

function rest_search_sites( WP_REST_Request $request ) {
    $value = $request->get_param( 'search' );

    $site = new WP_Site_Query();

    $sites_found = $site->query([
        'number' => 9999,
        'meta_query' => [
            'relation' => 'OR',
            [
                'key'     => 'site_name',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'country',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'continent',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'state',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'region',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'local_government_area',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
            [
                'key'     => 'city-town',
                'value'   => $value,
                'compare' => 'LIKE'
            ],
        ]
    ]);

    $result = new WP_REST_Response([]);

    if ( $sites_found ) {
        $sites = [];

        foreach ($sites_found as $s) {
            switch_to_blog($s->blog_id);

            $details = get_blog_details();
            $meta = get_site_meta($s->blog_id);

            $obj = new stdClass;

            $obj->blog_id = $s->blog_id;
            $obj->blogname = $details->blogname;
            $obj->siteurl = $details->siteurl;
            $obj->home = $details->home;
            $obj->meta = site_meta_object($meta);

            restore_current_blog();

            $sites[] = $obj;
        }

        $result = new WP_REST_Response( $sites );
    }

    $result->set_headers(array('Cache-Control' => 'max-age=3600'));

    return $result;
}

You are probably thinking I am crazy, but it works. I query the network using an OR meta query, meaning that only one of these has to match to return a result, and I do it for a few meta fields I have (created using ACF Pro).

The bit at the end is where I loop over the IDs. I get information about the site and construct an object of metadata and other details I might need on the front end.

It’s remarkably simple but powerful. This opens up the possibility of creating sites that are categorised by meta values and those values being searchable.

Dwayne

Leave a Reply Cancel reply

0 Comments
Inline Feedbacks
View all comments

Primary Sidebar

Popular

  • I Joined Truth Social Using a VPN and Editing Some HTML to Bypass the Phone Verification
  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript
  • How To Paginate An Array In Javascript
  • How To Mock uuid In Jest
  • How To Decompile And Compile Android APK's On A Mac Using Apktool
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • Wild Natural Deodorant Review

Recent Comments

  • CJ on Microsoft Modern Wireless Headset Review
  • Dwayne on Microsoft Modern Wireless Headset Review
  • CJ on Microsoft Modern Wireless Headset Review
  • john on Microsoft Modern Wireless Headset Review
  • Dwayne on Why You Should Be Using globalThis Instead of Window In Your Javascript Code

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz