(Revised answer to properly address the questions in the question..)
For Question 1 (JS)
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' )
}
For Question 2 (PHP)
I’d like to get a post in a form that looks identical to one retrieved
usinggetEntityRecords
.
-
Or maybe extend the
WP_REST_Posts_Controller
class (which is used with the standard posts routes likewp/v2/posts
). -
Or just make use of the
prepare_item_for_response()
andprepare_response_for_collection()
methods inWP_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, "https://wordpress.stackexchange.com/" . $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 );
}
}