WP API: Get posts excluding those with a tag or category name

I know from this post that I can get posts by tag name by just specifying a filter[tag] query parameter. And similarly with filter[category_name].

Is there a way to get posts that are not in a list of tags or categories for the purpose of excluding posts? I would prefer to do it with the name, or else I would have to make another request just to get the ID of the category, which would just slow down my overall response time in my app.

Topic wp-api tags Wordpress

Category Web


This is an old question but I think for now the solution exists.

We can use the tags_exclude=<tag-id> to execlude specifix tags.


You could try using the rest_post_query action to add exclusion filters for categories and tags. Try something like the below.

This adds ['filter']['exclude_categories'] and ['filter']['exclude_tags'] as options to use in the WP REST API. Each filter accepts multiple categories/tags seperated by a comma.

add_action( 'rest_post_query', 'your_exclude_query', 10, 2 );
function your_exclude_query( $args, $request ) {

    // Exclude Query
    if ( isset($request['filter']['exclude_categories']) || isset($request['filter']['exclude_tags']) ) {

        // If the exclude categories filter is set
        if ( isset($request['filter']['exclude_categories']) ) {
            $categories = explode( ',', $request['filter']['exclude_categories'] ); // NOTE: Assumes comma separated taxonomies
            array_push( $pre_tax_query, array(
                'taxonomy' => 'category',
                'field' => 'name',
                'terms' => array( $categories ),
                'operator' => 'NOT IN'
            ));
        }

        // If the exclude tags filter is set
        if ( isset($request['filter']['exclude_tags']) ) {
            $tags = explode( ',', $request['filter']['exclude_tags'] );  // NOTE: Assumes comma separated taxonomies
            array_push( $pre_tax_query, array(
                'taxonomy' => 'post_tag',
                'field' => 'name',
                'terms' => array( $tags ),
                'operator' => 'NOT IN'
            ));
        }

        $tax_query = array(
            'relation' => 'AND',
            $pre_tax_query
        );

        $args[ 'tax_query' ] = $tax_query;

    }

    return $args;

} // end your_exclude_query

So one way this can be done is by creating a filter to check for a custom query string parameter that represents a tag name or names.

I added a function similar to this to my theme. It modifies the global WP_Query object before a request is made for posts by the REST API.

add_filter('pre_get_posts', function ($query) {
        // I couldn't read from query_vars for some reason, so using global $_GET
        $exclude_tag_name = isset($_GET['exclude_tag_name']);

        if (!$exclude_tag_name) {
            return; // Nothing to do
        }

        // Whitelist for security
        // Add to this list as needed
        $whitelist = ['SomeExcludedTagNameHere'];

        $tag_name = $exclude_tag_name;

        // Additional logic goes here to handle multiple names, such as splitting

        // Check if tag name is in white list (with strict type checking)
        // For security, you could also probably use a REGEX to sanitize
        // or one of WP's built in sanitizing functions.
        if (!in_array($tag_name, $whitelist, true)) {
            return; // nothing to do
        }

        // Get all tags that contain this name (case insensitive)
        // Or just use the tag directly if it doesn't matter to you.
        $tags = get_tags([
            'search' => $tag_name
        ]);

        $tag_ids = [];
        foreach ($tags as $tag) {
            $tag_ids[] = $tag->term_id;
        }

        // Exclude these category IDs from the query
        if (!empty($tag_ids)) {
            // Modify the query object that was passed in by reference
            // This function uses the tag ID's not names!
            $query->set('tag__not_in', $tag_ids);
        }
});

Similar code can be used to include only posts that have been tagged with a particular tag.

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.