I'd like to get a post object from a custom REST endpoint within a Gutenberg block. The REST endpoint returns as part of its JSON payload an array with a "post" key which contains the contents of the WP_Post
PHP object to return. Normally I'd get posts with getEntityRecords
and withSelect
in the block's JavaScript:
// ...within gutenberg block...
edit: withSelect( ( select, props ) => {
const { attributes } = props;
const { getEntityRecords, getPostType } = select( 'core' );
const query = {
post_id: 5, // this is made up!
};
return {
children: getEntityRecords( 'postType', 'post', query )
};
} )( edit ),
...but this seems to only work for the standard WordPress posts REST endpoint. How can I get a post object from a custom REST endpoint within a Gutenberg block? Ideally I'd like to get a post in a form that looks identical to one retrieved using getEntityRecords
.
I'd like to get a post object from a custom REST endpoint within a Gutenberg block. The REST endpoint returns as part of its JSON payload an array with a "post" key which contains the contents of the WP_Post
PHP object to return. Normally I'd get posts with getEntityRecords
and withSelect
in the block's JavaScript:
// ...within gutenberg block...
edit: withSelect( ( select, props ) => {
const { attributes } = props;
const { getEntityRecords, getPostType } = select( 'core' );
const query = {
post_id: 5, // this is made up!
};
return {
children: getEntityRecords( 'postType', 'post', query )
};
} )( edit ),
...but this seems to only work for the standard WordPress posts REST endpoint. How can I get a post object from a custom REST endpoint within a Gutenberg block? Ideally I'd like to get a post in a form that looks identical to one retrieved using getEntityRecords
.
(Revised answer to properly address the questions in the question..)
How can I get a post object from a custom REST endpoint within a Gutenberg block?
So there's the apiFetch()
which you can use to fetch resources from the REST API.
But unlike return { children: getEntityRecords() }
, return { children: apiFetch() }
won't work because apiFetch()
always returns a Promise
instance — getEntityRecords()
always returns an object/array upon successful API request (and that the response is actually good).
So specifically if you want that to work with withSelect()
, then you can add your endpoint as an entity:
So in PHP, you can register a custom endpoint like so:
register_rest_route( 'my-namespace/v1', 'posts', array( ...your args... ) )
And in Gutenberg, you can add it as an entity like so:
var dispatch = wp.data.dispatch;
dispatch( 'core' ).addEntities( [
{
name: 'posts', // route name
kind: 'my-namespace/v1', // namespace
baseURL: '/my-namespace/v1/posts' // API path without /wp-json
}
]);
And then in your custom block:
// Used with withSelect():
return {
children: select( 'core' ).getEntityRecords( 'my-namespace/v1', 'posts' )
}
I'd like to get a post in a form that looks identical to one retrieved using
getEntityRecords
.
You can create your very own controller class.
Or maybe extend the WP_REST_Posts_Controller
class (which is used with the standard posts routes like wp/v2/posts
).
Or just make use of the prepare_item_for_response()
and prepare_response_for_collection()
methods in WP_REST_Posts_Controller
. These two methods can be used to return a list of posts.
Basic example for the third option (in actual implementation, you may want to add authorization/permissions check and/or accept custom parameters like per_page
):
class My_REST_Posts_Controller {
public function __construct() {
$this->namespace = '/my-namespace/v1';
$this->resource_name = 'posts';
}
public function register_routes() {
register_rest_route( $this->namespace, '/' . $this->resource_name, array(
array(
'methods' => 'GET',
'callback' => array( $this, 'get_items' ),
),
) );
}
public function get_items( $request ) {
$post_type = 'post'; // or this can be defined as a property in the class
$posts = get_posts( array(
'post_type' => $post_type,
) );
$data = array();
if ( empty( $posts ) ) {
return rest_ensure_response( $data );
}
// Here we make use of the default controller class.
// Remember that only a single post type is supported.
$class = new WP_REST_Posts_Controller( $post_type );
foreach ( $posts as $post ) {
$response = $class->prepare_item_for_response( $post, $request );
$data[] = $class->prepare_response_for_collection( $response );
}
return rest_ensure_response( $data );
}
}