Surfacing Gutenberg Blocks in the WordPress REST API

Gutenberg

The beauty of Gutenberg is that the HTML content is more structured and semantic while also simplifying the user experience. All of the data is stored in the post content, which is also great because we don’t have to request a bunch of post meta to render the page. On the other hand, if nothing is stored in post meta, how do you fetch this structured block data via the WordPress REST API?

When Gutenberg loads up blocks in the JavaScript, it actually parses your HTML to find the data it needs. So what do you do when you want to fetch that data in PHP?

Well, the comments that Gutenberg outputs in your post’s HTML are so Gutenberg can parse out your block’s data in PHP. The attributes in those comments aren’t necessarily used by Gutenberg in JavaScript. It is a redundant output so that PHP can parse your block data.

All you need to do to parse Gutenberg generated content into block data in PHP is use the gutenberg_parse_blocks() function. Just pass your content to that function and you will get back a JSON data structure representing the Gutenberg blocks on your page.

So how do we surface all that block data in the WordPress REST API?

Like so:

This will hook into the rest_api_init action and add our closure as a callback. We start by getting all post types that support the editor. Then, for each post type, we call gutenberg_can_edit_post_type()to check if our post type actually supports Gutenberg. If it does, we use the register_rest_field() function to add a blocksproperty to the object returned by the WordPress REST API. The get_callback bit is all we really need to declare since we are only concerned with outputting the blocks in the API. That get callback need only return a call to gutenberg_parse_blocks() after passing in the raw post content for the requested post.

Update: February 4, 2019

Now that Gutenberg has been merged into WordPress core, the Gutenberg-specific functions have been renamed in favor of a more generic naming convention. The gutenberg_can_edit_post_type() function is now use_block_editor_for_post_type() and the gutenberg_parse_blocks() function is now just parse_blocks().

Additionally, the use_block_editor_for_post_type() function lives in the wp-admin/includes/post.php file, which is not loaded on the rest_api_init hook. As such, we have to load that file ourselves to be able to use that function.

<?php

add_action(
	'rest_api_init',
	function () {

		if ( ! function_exists( 'use_block_editor_for_post_type' ) ) {
			require ABSPATH . 'wp-admin/includes/post.php';
		}

		// Surface all Gutenberg blocks in the WordPress REST API
		$post_types = get_post_types_by_support( [ 'editor' ] );
		foreach ( $post_types as $post_type ) {
			if ( use_block_editor_for_post_type( $post_type ) ) {
				register_rest_field(
					$post_type,
					'blocks',
					[
						'get_callback' => function ( array $post ) {
							return parse_blocks( $post['content']['raw'] );
						},
					]
				);
			}
		}
	}
);

Comments

  1. Interesting solution.

    The anonymous functions are only supported by PHP 7.0+.

    It would be nice to include “compatible” code for this.

    But with your post, you surfaced everything that is currently wrong with WordPress.

    Gutenberg is powered by modern-day Javascript while the backend standards are so far behind it’s not even funny.

    I would also love to know what Google is planning to offer WordPress or if there will be needed breaking changes to the core to improve speed and performance.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.