Skip to content
This repository has been archived by the owner on Aug 27, 2019. It is now read-only.

Add guide for WP developers #190

Open
wants to merge 3 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions for-wp-developers/best-practices.md
Original file line number Diff line number Diff line change
@@ -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`:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are also available via the settings API.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Settings is only available when you have manage_options, so not really a general purpose solution, alas.


```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' ),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would I do: You selected the %s post in a translation for the front-end?

));
```

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.
80 changes: 80 additions & 0 deletions for-wp-developers/index.md
Original file line number Diff line number Diff line change
@@ -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.

<div class="note" markdown="1">
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/).
</div>

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.

<div class="note" markdown="1">
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()`.
</div>

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/).
33 changes: 33 additions & 0 deletions for-wp-developers/internal.md
Original file line number Diff line number Diff line change
@@ -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', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should use a fetch example rather than jQuery?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming most WordPress developers aren't familiar with fetch and also aren't going to be any time soon.

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 );
```