WordPress REST API post orderby custom value

tl;dr: Ordering posts by menu_order doesn’t work out of the box with the WP REST API. To enable this you need to add a filter to rest_{post_type}_collection_params for each post type you want to order by menu_order.

The WP REST API is a great addition to WordPress, made even better in v2. It enables us to do some great things with Javascript on the front end of the site, and also gives a great way of doing batch updates, from scripts and other serverside code outside the wordpress environment.

In a recent project I needed to display the posts from the REST API in a custom order. This is not possible in on custom post types normally, so I installed a plugin to do the work in the admin area for me. Simple Custom Post Order allows you to drag and drop the order of the posts in the admin view. This is exactly what I needed.

Behind the scenes in the database, the plugin updates the column menu_order in the posts table. So to display the posts in the custom order in the front end, the WP_Query needs to have an orderby parameter set to menu_order. Easy if you are building a WP_Query directly. Its not so easy in the REST API though, there is an orderby parameter enabled for the WP REST API, but by default, the only values you can sort by are: author, date, id, include, modified, parent, relevance, slug, include_slugs, title.

If you try to orderby another value, then you get an error from the REST API:

{
  "code": "rest_invalid_param",
  "message": "Invalid parameter(s): orderby",
  "data": {
    "status": 400,
    "params": {
      "orderby": "orderby is not one of author, date, id, include, modified, parent, relevance, slug, include_slugs, title."
    }
  }
}

Luckily there is a WordPress filter that allows you to modify this list of values and orderby anything you want. The filter hook is called rest_{post_type}_collection_params. You can see how to use it in the following gist:

<?php
/**
* The filter is named rest_{post_type}_collection_params. So you need to hook a new filter for each
* of the custom post types you need to sort.
* @link https://www.timrosswebdevelopment.com/wordpress-rest-api-post-order/
*/
// This enables the orderby=menu_order for Posts
add_filter( 'rest_post_collection_params', 'filter_add_rest_orderby_params', 10, 1 );
// And this for a custom post type called 'portfolio'
add_filter( 'rest_portfolio_collection_params', 'filter_add_rest_orderby_params', 10, 1 );
/**
* Add menu_order to the list of permitted orderby values
*/
function filter_add_rest_orderby_params( $params ) {
$params['orderby']['enum'][] = 'menu_order';
return $params;
}

With this filter enabled, now you can make a request to the WP REST API and get the posts back in exactly the order you need. No more rest error messages.

https://www.timrosswebdevelopment.com/wp-json/wp/v2/posts?orderby=menu_order&order=asc

And the posts should be listed exactly as they are defined in the admin area.

9 thoughts on “WordPress REST API post orderby custom value

  1. (so sorry my poor english)

    thank you!
    it’s a great help for me.

    but I’m in troubled.
    it’ work on post, but not work on category

    i add ↓ after line.9 of your sample code.
    ——————
    add_filter( ‘rest_category_collection_params’, ‘filter_add_rest_orderby_params’, 10, 1 );
    ——————

    after wrote that, i can get by data by
    —————
    /categories?orderby=menu_order
    —————
    but don’t be in order admin screen setting

    what i should wrote for category sort?

  2. I’m send mail about 1 week before.

    then, I said can’t sort category,
    but, I can this, after re-install Simple Custom Post Order plugin.

    so sorry…

    this mail just said apology and thanks!
    this code so useful for me!

  3. Hi Tim, thanks for this article. I came up with sorting woo products in menu_order. So what I did i added a filter with rest_product_collection_params but it doesn’t do the job. Do you have an idea wether this is not working for woo products? Thanks in advance! Micha

  4. This works!! Super, thank you for sharing.

    It solved my problem for displaying related posts on a page (without being too predictable and showing always the same postst).

  5. Hmmm… Maybe I’m doing something wrong:

    In functions.php:
    add_filter( ‘rest_photographs_collection_params’, ‘filter_add_rest_orderby_params’, 10, 1 );

    function filter_add_rest_orderby_params( $params ) {
    $params[‘orderby’][‘enum’][] = ‘cf_photo_date’;
    return $params;
    }

    query in browser: https://oursite.com/wordpress/wp-json/wp/v2/photographs?orderby=cf_photo_date&order=asc

    The above stops the error but doesn’t actually order the posts. cf_photo_date is set as a number in acf but same issue with other fields set as text.

    Any ideas?

    1. Stefan, in this post I only talk about ordering by ‘menu_order’ which is a built-in field in WordPress and you can already see in the REST API.

      If you want to order the posts by a custom field, then you should take a look at my other post about ordering posts by custom fields or ‘meta_value’. For this you need to use a WordPress meta_query in the REST API, and my post details how to achieve that.

      Feel free to leave a comment on the other post if you are still having trouble.
      Thanks,
      Tim

Leave a Reply

Your email address will not be published. Required fields are marked *