WordPress plugin that extends WPGraphQL to support querying (Gutenberg) Blocks as data.
This plugin is an extension of wp-graphql
, so make sure you have it installed first.
- Download the latest .zip version of the plugin
- Upload the plugin .zip to your WordPress site
- Activate the plugin within WordPress plugins page.
There is no other configuration needed once you install the plugin.
Once the plugin is installed, head over to the GraphiQL IDE and you should be able to perform queries for the block data (This plugin is an extension of wp-graphql, so make sure you have it installed first.).
There is a new field added in the Post and Page models called editorBlocks
.
This represents a list of available blocks for that content type:
{
posts {
nodes {
# editorBlocks field represents array of Block data
editorBlocks(flat: false) {
# fields from the interface
renderedHtml
__typename
# expand the Paragraph block attributes
... on CoreParagraph {
attributes {
content
}
}
# expand a Custom block attributes
... on CreateBlockMyFirstBlock {
attributes {
title
}
}
}
}
}
}
To query specific block data you need to define that data in the editorBlocks
as the appropriate type.
For example, to use CoreParagraph
attributes you need to use the following query:
{
posts {
nodes {
editorBlocks(flat: false) {
__typename
name
... on CoreParagraph {
attributes {
content
className
}
}
}
}
}
}
If the resolved block has values for those fields, it will return them, otherwise it will return null
.
{
"__typename": "CoreParagraph",
"name": "core/paragraph",
"attributes": {
"content": "Hello world",
"className": null
}
}
In order to facilitate querying innerBlocks
fields more efficiently you want to use editorBlocks(flat: true)
instead of editorBlocks
.
By passing this argument, all the blocks available (both blocks and innerBlocks) will be returned all flattened in the same list.
For example, given the following HTML Content:
<columns>
<column>
<p>Example paragraph in Column</p>
<p></p
></column>
<column></column
></columns>
It will return the following blocks:
[
{
"__typename": "CoreColumns",
"name": "core/columns",
"id": "63dbec9abcf9d",
"parentClientId": null
},
{
"__typename": "CoreColumn",
"name": "core/column",
"id": "63dbec9abcfa6",
"parentClientId": "63dbec9abcf9d"
},
{
"__typename": "CoreParagraph",
"name": "core/paragraph",
"id": "63dbec9abcfa9",
"parentClientId": "63dbec9abcfa6",
"attributes": {
"content": "Example paragraph in Column 1",
"className": null
}
}
]
The CoreColumns
contains one or more CoreColumn
block, and each CoreColumn
contains a CoreParagraph
.
Given the flattened list of blocks though, how can you put it back? Well that's where you use the `` and parentId
fields to assign temporary unique ids for each block.
The clientId
field assigns a temporary unique id for a specific block and the parentClientId
will
be assigned only if the current block has a parent. If the current block does have a parent, it will get the parent's clientId
value.
So in order to put everything back in the Headless site, you want to use the flatListToHierarchical
function as mentioned in the WPGraphQL docs.
Currently the
clientId
field is only unique per request and is not persisted anywhere. If you perform another request each block will be assigned a newclientId
each time.
With this update, you can now query object-type block attributes with each property individually, provided that the typed structure is defined in the class typed_object_attributes
property or through a WordPress filter.
The typed_object_attributes
is a filterable array that defines the expected typed structure for object-type block attributes.
- The keys in
typed_object_attributes
correspond to object attribute names in the block. - Each value is an associative array, where:
- The key represents the property name inside the object.
- The value defines the WPGraphQL type (e.g.,
string
,integer
,object
, etc.).
- If a block attribute has a specified typed structure, only the properties listed within it will be processed.
Typed object attributes can be defined in two ways:
Developers can extend the Block
class and specify typed properties directly:
class CustomMovieBlock extends Block {
/**
* {@inheritDoc}
*
* @var array<string, array<string, "array"|"boolean"|"number"|"integer"|"object"|"rich-text"|"string">>
*/
protected array $typed_object_attributes = [
'film' => [
'id' => 'integer',
'title' => 'string',
'director' => 'string',
'soundtrack' => 'object',
],
'soundtrack' => [
'title' => 'string',
'artist' => 'string'
],
];
}
You can also define typed structures dynamically using a WordPress filter.
add_filter(
'wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block',
function () {
return [
'film' => [
'id' => 'integer',
'title' => 'string',
'director' => 'string',
'soundtrack' => 'object',
],
'soundtrack' => [
'title' => 'string',
'artist' => 'string'
],
];
}
);
To apply custom typing via a filter, use the following format:
wpgraphql_content_blocks_object_typing_{block-name}
- Replace
/
in the block name with-
. - Example:
- Block name:
my-custom-plugin/movie-block
- Filter name:
wpgraphql_content_blocks_object_typing_my-custom-plugin_movie-block
- Block name:
If the block has attributes defined as objects, like this:
"attributes": {
"film": {
"type": "object",
"default": {
"id": 1,
"title": "The Matrix",
"director": "Director Name"
}
},
"soundtrack": {
"type": "object",
"default": {
"title": "The Matrix Revolutions...",
"artist": "Artist Name"
}
}
}
This means:
- The
film
attribute containsid
,title
,director
. - The
soundtrack
attribute containstitle
andartist
.
Once the typed object attributes are defined, you can query them individually in WPGraphQL.
fragment Movie on MyCustomPluginMovieBlock {
attributes {
film {
id
title
director
soundtrack {
title
}
}
soundtrack {
title
artist
}
}
}
query GetAllPostsWhichSupportBlockEditor {
posts {
edges {
node {
editorBlocks {
__typename
name
...Movie
}
}
}
}
}
All external contributors to WP Engine products must have a signed Contributor License Agreement (CLA) in place before the contribution may be accepted into any WP Engine codebase.
- Submit your name and email
- 📝 Sign the CLA emailed to you
- 📥 Receive copy of signed CLA
❤️ Thank you for helping us fulfill our legal obligations in order to continue empowering builders through headless WordPress.