The REST API in WordPress 5.0. Solid set of improvements in these dev notes — thanks everyone who contributed!
This post originally appeared on make.wordpress/core.
Since I last wrote two weeks ago, we’re making progress! Key achievements for Gutenberg and the REST API include:
- Support for
who=authorswas added to
GET wp/v2/users, making it possible to accurately query for authors. WordPress, for better or for worse, defines an author as
user_level!=0. See WordPress/gutenberg#6361 for the context on why we can’t add this logic client-side (#42202 for WordPress 4.9.6).
- Improved performance for the
_fields=query parameter (e.g.
GET wp/v2/pages?_fields=id,title) by ensuring WordPress core will only process the fields requested for the response. Notably, this helps us avoid running
the_contentwhen we don’t need to be (#43874 for WordPress 4.9.7).
- Minor enhancements to reflect existing WordPress behaviors:
- Disables the Preview button when post type isn’t viewable (WordPress/gutenberg#6232 for Gutenberg 2.7)
- Filters the Post Format list to only formats that are supported (WordPress/gutenberg#6296 for Gutenberg 2.8)
- Only displays Featured Image UI when theme supports it too (WordPress/gutenberg#6541 for Gutenberg 2.8)
The “Merge Proposal: REST API” GitHub milestone represents the distance we still need to close. Slowly, steadily, we’re bridging the gap, but we could use your help. Here are some of the issues we’re still working through:
- To ensure all necessary data is available to Gutenberg, we’ve settled upon permitting unbounded
per_page=-1REST API requests for authorized users. This landed for
GET wp/v2/users(WordPress/gutenberg#6627), is in-progress for
GET wp/v2/(pages|blocks)(WordPress/gutenberg#6657), and needs to be addressed for categories, tags, and custom taxonomies. We also need to patch core with this enhancement (#43998 for WordPress 4.9.7?)
- Capabilities can’t be processed directly client-side (WordPress/gutenberg#6361), so we’ve introduced a new
targetSchemaconcept to communicate which actions a user can perform. See it in action with
wp:action-assign-author(WordPress/gutenberg#6630). There are a few other actions we will need to work out, and then we’ll need to patch core (no ticket yet).
- Adam is putting together an improved autosaves implementation (WordPress/gutenberg#6257) that I literally cannot wait to see complete. I’m sure he could use some help testing in the near future.
- Felix is implementing a
WP_REST_Search_Controllerendpoint (WordPress/gutenberg#6489) to power the link search UI.
Join us tomorrow, Thursday, May 10 at 17:00 UTC in
#core-restapi office hours if you’d like to chat through any questions you have.
Musings on the WordPress REST API. I did a webinar (gag) with Pantheon covering real world examples, writing custom endpoints, and including test coverage. Turned out surprisingly well, if I do say so myself.
eval-file command in
wp profile, you can profile key performance metrics for a WP REST API response by mocking, executing, and evaluating the request with a one-off file. These key performance metrics include execution time, query count, cache hit/miss ratio, and more.
For example, to mock a call to
GET /wp/v2/posts?per_page=100, you’d create a
get-posts.php file like this:
<?php $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); $request->set_param( 'per_page', 100 ); $server = rest_get_server(); $server->dispatch( $request );
get-posts.php by running
wp profile eval-file get-posts.php:
$ wp profile eval-file get-posts.php +---------+------------+-------------+-------------+------------+--------------+--------------+---------------+ | time | query_time | query_count | cache_ratio | cache_hits | cache_misses | request_time | request_count | +---------+------------+-------------+-------------+------------+--------------+--------------+---------------+ | 0.9429s | 0.002s | 5 | 96.39% | 7599 | 285 | 0s | 0 | +---------+------------+-------------+-------------+------------+--------------+--------------+---------------+
By filtering the
rest_authentication_errors filter, you can return a 401 error if the request isn’t authenticated.
You absolutely need test coverage for your WP REST API project. I wrote a tutorial for Pantheon that I hope becomes the canonical reference point for everyone considering whether or not to write tests for their endpoints — please do.
First of all, don’t expect much of this blog post. It’s intended to capture some thoughts and opinions I’ve noted down while working on my first real-world React / WP REST API application. It’s not intended to be polished, professional-grade marketing copy. It also assumes you have some familiarity with React, Redux, and the WP REST API — if you don’t, the blog post may not make sense. You’ve been warned.
I pretty much love React at this point, and can’t imagine using WordPress’ theming for anything in the future. If you hire me to build a brochure website, I will probably build it in React, just because.
What I like most is that everything is so damn elegant. The component-based architecture encourages you to think about whatever you’re building in terms of reusable pieces. I suspect this naturally lends itself to Better Quality Code.
But, React is also a substantial departure from WordPress’ quick and dirty ethos. A concern of mine is long-term maintainability of a React-based website, particularly for clients who think they’re getting a WordPress website and expect to be able to hire a WordPress developer for future changes to it.
Routing is painful. I haven’t found an elegant solution to the fact that routes need to be declared in WordPress and in React.
For the project I’m on, all routes are going into React first so the application works as expected. At some point, I’ll need to figure out how equivalent routes should be sustainably registered as WordPress rewrites.
The theory is that single page applications deployed as WordPress themes can use WordPress to serve response headers, social / SEO meta, and prepare an initial payload of data using the main query, before passing on the torch to React. In practice, I’ve worked very little of this out yet.
Or, I can noop WordPress’ route handling entirely, but then I’ll lose some of the benefit of having WordPress serving the initial pageload.
Which brings me to managing application state. Once you get over the day of effort to understand how Redux works, it’s really quite elegant. It also takes about 50% more effort than I’d like to get my application data into my components.
If I may make one request, could someone please write a redux-wp library to magically generate actions and reducers from my WP REST API index?
If you’re curious what real-world WP REST API endpoint registration looks like, here’s the Controller for a Record which, in the LMS data model of students completing activities and quizzes, stores the data of a student’s answers to an activity or quiz.
Commentary on my code, in no particular order, includes:
- I’m not sure why I’m using
register_rest_field()when I’m already subclassing and have access to the schema. I should probably refactor that.
- Make sure to register your fields before your routes, if you’re using the helpers to transform schema into route args. This bit me once.
- While it’s nice I can use a filter to modify the behavior of
WP_REST_Posts_Controller->get_items(), aforementioned method is impossible to subclass.
- The REST API’s concept of context (e.g. embed vs. view vs. edit) is mostly useless in my case, because I’m always fetching the entirety of the resource. I would like for a way to easy disable the concept of context. Also, we should’ve gone with
title_renderedinstead of creating a title object on the Post resource.
arg_optionsalways feels really awkward, because registering a schema property seems like it should be equivalent to registering a query parameter or anything else. I want to be able to use
default, and others as top-level arguments to registering a schema property.
Generally, I consider the WP REST API controllers to be good, but not great, right now. I’m writing lots of tests for cases I don’t think I should need to write tests for, because the WP REST API is a bit leaky. For instance, I’d expect for my declaration of query params and schema to be the canonical truth of what the endpoint supports, which isn’t the case currently (e.g. you can deregister the
password field on a Post-derived resource, and password will still be included in the response object).
In my ideal world, to create a custom post type endpoint, I would:
- Define the shape of my resource (e.g. its schema)
- Declare which operations the resource supports (list, get, create, update, delete) through some means where I didn’t have to extend
- Declare which query params the resource supports.
- Implement permissions checks as needed.
Leave me any questions you have in the comments! Or, better yet, write about the real-world lessons you’ve learned.
Earlier today, I tweeted:
Right about now seems like a good time to get official feedback on WP REST API from @wordpress’s lead developers and committers. Just sayin’
Helen, a lead WordPress developer, replied with:
Where does this feedback go, how is it structured, what makes it “official”, and how binding is anything that is said?
To which I replied:
maybe: 1) make/core or personal blog posts 2) I have suggestions 3) comes from your voice 4) actual goal: build consensus
There’s a lot of background to this exchange. If it doesn’t make sense to you, first read this WP Tavern post and then read this Post Status post. The tldr: we’re at a juncture for the WP REST API (a good thing!) where we’ve completed a ton of work (four years for Ryan, in fact) and need to make decisions on whether it’s ready to be merged, or needs additional work before merge consideration.
And we need to make these decisions as a group. Of individuals. With very different: backgrounds, opinions, experience levels with the REST API, and experience levels with other APIs. I’m sure you all know how group decision making goes.
Before we make decisions though, it would be incredibly helpful to have as much information on the table as possible — so everyone can know all sides of the decisions we need to make. This is why I publicly requested “official” feedback on the WP REST API from the WordPress project’s lead and contributing developers:
The feedback doesn’t need to be of any particular form. Jeremy Felt already posted his, which is A+, very much appreciate. And, we (Ryan, Rachel, Joe and I) would love constructive feedback from anyone and everyone — but WordPress’ lead developers and committers are the ones who will be maintaining this project for the long term.
If you’re looking for inspiration on how to get started, I typically try to frame my feedback as:
- What I like.
- What I’d like to see improved.
Both of these could cover:
- What you like about the features the REST API supports, and which features you think are a priority to add before merge (and after).
- Of our documentation, what topics you find explained well, and which should we focus our efforts to improve upon.
- Of our codebase, what abstractions and patterns you find delightful, and which you think are confusing.
- What you like about how we’ve conducted the project so far, and what changes you think we need make for the next six months to be successful, and the twelve months after that.
Ultimately, “should we merge it?” is a binary decision. But, getting as many perspectives as possible out in the open will help us better explore the potential ramifications of the decision, which is more important than the decision itself.
If you don’t want to post on your personal blog, then leaving a comment on this post is a great place for your feedback. Thanks in advance!
The proposal by the team was to include the 4 content endpoints when they are ready. We had a lengthly overview as to the progress of those endpoints, more details on what we feel is left to be done can be seen at https://github.com/wp-api/wp-api/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.0
Why these endpoints specifically? Because they are co-dependent for the most part. Shipping Posts without support for Taxonomies would not be that useful.
Going for development of _all_ functionality (somewhere around 8-10 total data routes) should not be underestimated. It’s taken somewhere around a year and a half to get the current 4 to where they are now, and that was with 2 years prior art from Version 1.
As someone who has been in the weeds of that implementation for a while now, I cannot over over-stress just how tricky trying to retrofit a consistent, coherent interface on 13 years of organically grown code and ideas can become. I’m looking forward to being part of the writing the implementation for the remaining (and majority) of functionality, however I don’t want to stop users and developers benefitting from what is already being built for another [several] years.
WP REST API: Version 2.0 Beta 12. “Canyonero”