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 blocks
property 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. gutenberg_can_edit_post_type()
use_block_editor_for_post_type()
gutenberg_parse_blocks()
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'] );
},
]
);
}
}
}
);