From 4c39f2b19286dc6edb50dfe46770e7b43716c95f Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Thu, 3 Nov 2016 17:23:49 +1000 Subject: [PATCH 1/3] Add first pass at a guide for WP developers --- for-wp-developers/index.md | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 for-wp-developers/index.md diff --git a/for-wp-developers/index.md b/for-wp-developers/index.md new file mode 100644 index 0000000..6f7c26b --- /dev/null +++ b/for-wp-developers/index.md @@ -0,0 +1,80 @@ +--- +title: For WordPress Developers +--- + +Already a WordPress developer? The REST API can help you build faster and write less code, so you can focus on building your awesome plugin or theme. + +A lot of the REST API will be familiar to you, but there are some important differences in the data, and new terminology specific to the REST API. + + +## Terminology + +controller +: Class containing everything needed for a route, including registration, sanitization callbacks, and the main callback. + +endpoint +: Callback that responds to a HTTP request. Tied to a route and HTTP method. + +route +: URL pattern, equivalent to a WordPress rewrite rule. Can have multiple endpoints to handle multiple HTTP methods. + +resource +: Object stored in WordPress, such as a post or term. + +schema +: Meta-object which describes what a resource looks like. + + +## Structure + +The REST API is a whole new external API for WordPress installations. The API is designed around a concept called [REST, or Representation State Transfer](https://en.wikipedia.org/wiki/Representational_state_transfer), which uses HTTP requests to interact with data. If you've ever sent a HTTP request or used Ajax, you'll be right at home using the REST API. + +The API lives under `/wp-json/` on WordPress sites (you can get this URL from `rest_url()`), and is broken down into a bunch of "routes". You can think of routes as rewrite rules that map your request to the internal API code used to handle the request. + +
+REST API routes are not directly registered as rewrite rules, as they follow a different style of internal rewriting. For information on how to add your own routes, see [the Adding Endpoints guide](http://localhost:4000/extending/adding/). +
+ +Each route in the REST API has a namespace, the route itself, and the endpoints registered for it. The namespace is similar to PHP namespaces or function prefixes; for WordPress core, the namespace is "wp/v2". The route is a regular expression to match against the URL, similar to a rewrite rule. This is matched by the API infrastructure to an endpoint, which is a callback function. Unlike rewrite rules, endpoints are tied to specific HTTP methods; a route can have both a `GET` endpoint **and** a `POST` endpoint. + +Since the REST API is based on HTTP, working with it involves things you'll already know: `GET` and `POST` requests. REST also uses two other verbs, `PUT` and `DELETE`, and codifies exactly what they mean: + +* `GET` - Retrieve a resource +* `POST` - Create a resource +* `PUT` - Update a resource +* `DELETE` - Delete a resource + +Routes fall into one of two buckets: single resources, and collections. Resources are objects, like posts, while collections are arrays of resources. + + +### Resources + +The REST API returns a bunch of different objects to the client. These objects are called "resources"; you can imagine them just like objects in PHP, where the object type is similar to the PHP class. + +In WordPress, there are four fundamental data types: posts, comments, terms, and users. These types (excluding users) can have subtypes as well: custom post types, custom comment types, and taxonomies. The REST API contains full support for all of these types and subtypes. + +Each of these subtypes has a "schema", which is similar to a PHP class, and describes "resources" of that type. Resources are the actual objects available through the API. For example, pages have a set schema, and a page called "About" would be a resource following the page schema. + +
+If you want to expose your custom resource (custom post type, etc) via the REST API, you need to [opt-in in your registration call](/extending/custom-content-types/). Exposing the resource via the REST API here will use the default controllers built into the REST API, which [you can subclass](/extending/internal-classes/) or you can [create your own endpoints instead](/extending/adding/). The schema for your type will be automatically generated from the internal WordPress registration data, such as `post_type_supports()`. +
+ +Resources returned through the API are similar to the internal PHP object, but typically use different names. The API intentionally changes these names to make them more consistent, but this means they differ from the internal names you might be used to. Generally, we use the user-facing terminology, rather than internal names; that means `title` instead of `post_title` and `featured_media` instead of `post_thumbnail`. The [API reference](/reference/) contains details about all properties available for every resource. + +Resources are typically singular, and live at URLs like `/wp/v2/posts/42`; that is, `/wp/v2/{object}s/{id}`. They can be retrieved with `GET`, updated with `PUT`, and deleted with `DELETE`. You can also get information about the route and the resource schema by sending an `OPTIONS` request. + + +### Collections + +Collections are an array of resources. They're similar to the query classes (`WP_Query` and friends) in WordPress. + +Just like resources, the names are changed from the internal names to be more consistent. Typically, query parameters match the field you want to query by; to find posts with `status` set to `draft`, simply query `status=draft`. All collection query parameters are included in the `OPTIONS` response, and are also listed in the [API reference](/reference/). + +Collections are typically plural, and live at URLs like `/wp/v2/posts`; that is `/wp/v2/{object}s`. They can be retrieved with `GET`, and new resources can be created with `POST`. You can also get information about the route and the schema for the resources it contains by sending an `OPTIONS` request. + + +## Requesting Data + +To use the REST API, your code needs to send HTTP requests to the API endpoints you want to access. If you want to access protected data (`raw` fields for editing) or update data, you'll also need to a) be logged in, and b) send a nonce with your request. Nonces can be generated with `wp_create_nonce( 'wp_rest' )`, and should be sent as the `_wpnonce` parameter in the query string (i.e. `/wp-json/?_wpnonce=abcd123`). + +The API also bundles [a Backbone library](/extending/javascript-client/) including models and collections, which can be used to format and send requests for you, automatically handling authentication and encoding. This library can be used even if you're not using Backbone in your own code. Simply declare `wp-api` as a dependency of your script when you enqueue it. Further information on how to use the library is available [on the JavaScript Client page](http://localhost:4000/extending/javascript-client/). From 1e7e2e1316246c144264ee4b65a04aa67eb0a084 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Sun, 6 Nov 2016 00:37:48 +1000 Subject: [PATCH 2/3] Add start of best practices guide --- for-wp-developers/best-practices.md | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 for-wp-developers/best-practices.md diff --git a/for-wp-developers/best-practices.md b/for-wp-developers/best-practices.md new file mode 100644 index 0000000..654ed71 --- /dev/null +++ b/for-wp-developers/best-practices.md @@ -0,0 +1,63 @@ +--- +title: Best Practices +--- + +## Display Formatting + +WordPress includes a number of formatting utilities along with configuration, which aren't available via the API directly. While WordPress has traditionally being a large monolithic program, the API separates concerns into either backend or frontend, with the API handling backend interactions while your app handles the frontend display. This means that you need to handle formatting output yourself. + +### Date & Time Formatting + +Date & time formatting is not handled in the API. All API datetimes are provided in ISO 8601 (RFC 3339, `date('r')`) format; that is: `YYYY-MM-DDThh:mm:ssZ`. This datetime then needs to be formatted as appropriate for display to users. + +If you want to follow the site date/time formatting settings in JavaScript, you need to pass the `date_format` and `time_format` settings to your script, then translate these into their equivalents for the relevant library you're using. These options can be passed via `wp_localize_script`: + +```php +wp_enqueue_script( 'my-plugin-script', plugins_url( 'my-script', __FILE__ ), array( 'wp-api' ) ); +wp_localize_script( 'my-plugin-script', 'MyPluginScriptVars', array( + 'date_format' => get_option( 'date_format' ), + 'time_format' => get_option( 'time_format' ), + + // You may also need the timezone: + 'timezone' => get_option( 'timezone_string' ), + + // If you are displaying a calendar, you may need the "Week Starts On" setting: + 'start_of_week' => get_option( 'start_of_week' ), +)); +``` + +Note that unlike PHP, JavaScript doesn't include date formatting utilities, so a library is required. There are a number of libraries that can take PHP formats directly: + +* [php-date-formatter](https://github.com/kartik-v/php-date-formatter) +* [Locutus](http://locutus.io/php/datetime/date/) (previously php.js) + +There are also libraries which can format dates, but take other formats, so will need a translation layer: + +* [Moment.js](http://momentjs.com/) +* [dateformat](https://github.com/felixge/node-dateformat) + + +### Localization + +Similar to date and time formatting, localization and translation are considered a frontend concern. If you have user-facing text, you may need to translate this yourself. You can use `wp_localize_script` to handle this, which allows passing translations to your plugin: + +```php +wp_localize_script( 'my-plugin-script', 'MyPluginScriptTranslations', array( + 'name' => __( 'My Plugin', 'my-plugin' ), + 'select_post' => __( 'Select a post...', 'my-plugin' ), +)); +``` + +You can then pull these out into your display code through `MyPluginScriptTranslations.select_post`. This also allows you to use the relevant text domain for your plugin, rather than WordPress core's text domain, ensuring your plugin consistently displays text in a single language. + +Some translations are available in the API's schema. This typically applies to field descriptions, which are included in the API, are human-readable, and fully translated by the API. These descriptions are intended mainly for developers, so may not always be suitable for users. + + +## Backwards Compatibility + +Filters. + + +## Server-Side Rendering + +For performance, accessibility, or caching purposes, you might want to render your code on the server-side as well as on the frontend. From c7c2e3ab9d5eebaf937bf2d773adb201f8ad5fcc Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Sun, 6 Nov 2016 00:38:11 +1000 Subject: [PATCH 3/3] Add docs on internal usage --- for-wp-developers/internal.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 for-wp-developers/internal.md diff --git a/for-wp-developers/internal.md b/for-wp-developers/internal.md new file mode 100644 index 0000000..79bf396 --- /dev/null +++ b/for-wp-developers/internal.md @@ -0,0 +1,33 @@ +--- +title: Internal Reuse +--- + +If you're writing code to work with the REST API, but still want things handled in PHP, you might notice that you need to duplicate code to handle differences between the API and internal functions. The REST API provides an internal, PHP-based API that you can use to do everything you do through the external, HTTP-based API. + +The key function for performing internal requests is [`rest_do_request()`](https://developer.wordpress.org/reference/functions/rest_do_request/). This function takes a [`WP_REST_Request` object](https://developer.wordpress.org/reference/classes/wp_rest_request/) and returns a [`WP_REST_Response` object](https://developer.wordpress.org/reference/classes/wp_rest_response/). You can use these to + +For example, you may have code that renders a post into HTML, and want to use this on the server as well. Let's say your frontend code looks something like this: + +```js +$.ajax( '/wp/v2/posts/42', { + error: function () { + handleError(); + }, + success: function (data) { + render( data ); + } +}) +``` + +You could do the same request inside your PHP code with the following: + +```php +$request = new WP_REST_Request( 'GET', '/wp/v2/posts/42' ); +$response = rest_do_request( $request ); +if ( $response->is_error() ) { + return handleError(); +} + +$data = $response->get_data(); +render( $data ); +```