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:
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.
And the posts should be listed exactly as they are defined in the admin area.
(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?
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!
I’m glad you found the code helpful Yuki. 🙂
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
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).
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?
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
Great article that helped me resolve my issue in a timely manner, gotta appreciate the wins! Thanks