WP_Block_Templates_Registry
Core class for interacting with registered templates.
Since: 6.7.0
Source: wp-includes/class-wp-block-templates-registry.php
Description
WP_Block_Templates_Registry is a singleton that allows plugins to programmatically register block templates. This provides a way to define templates without requiring theme files.
Properties
$registered_templates (private)
Registered templates as $name => $instance pairs.
private WP_Block_Template[] $registered_templates = array()
Since: 6.7.0
$instance (private static)
Container for the main singleton instance.
private static WP_Block_Templates_Registry|null $instance = null
Since: 6.7.0
Methods
get_instance()
Retrieves the main singleton instance.
public static function get_instance(): WP_Block_Templates_Registry
Returns: (WP_Block_Templates_Registry) – The main instance
Since: 6.7.0
register()
Registers a template.
public function register(
string $template_name,
array $args = array()
): WP_Block_Template|WP_Error
Parameters:
$template_name(string) – Template name including namespace (format:plugin//slug)$args(array) – Optional. Template arguments:content(string) – Block contenttitle(string) – Human-readable titledescription(string) – Template descriptionpost_types(string[]) – Post types this template applies to
Returns: (WP_Block_Template|WP_Error) – Registered template or error
Since: 6.7.0
Validation Rules:
- Name must be a string
- Name must not contain uppercase characters
- Name must follow pattern:
plugin//slug - Template must not already be registered
Example:
$registry = WP_Block_Templates_Registry::get_instance();
$template = $registry->register( 'my-plugin//product-showcase', array(
'title' => 'Product Showcase',
'description' => 'A template for displaying product features',
'content' => '<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading -->
<h2>Featured Product</h2>
<!-- /wp:heading -->
<!-- wp:post-featured-image /-->
<!-- wp:post-content /-->
</div>
<!-- /wp:group -->',
'post_types' => array( 'product' ),
) );
unregister()
Unregisters a template.
public function unregister( string $template_name ): WP_Block_Template|WP_Error
Parameters:
$template_name(string) – Template name including namespace
Returns: (WP_Block_Template|WP_Error) – Unregistered template or error
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
$result = $registry->unregister( 'my-plugin//product-showcase' );
if ( is_wp_error( $result ) ) {
echo $result->get_error_message();
}
get_registered()
Retrieves a registered template by name.
public function get_registered( string $template_name ): WP_Block_Template|null
Parameters:
$template_name(string) – Template name including namespace
Returns: (WP_Block_Template|null) – Registered template or null
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
$template = $registry->get_registered( 'my-plugin//product-showcase' );
if ( $template ) {
echo $template->title;
}
get_by_slug()
Retrieves a registered template by slug.
public function get_by_slug( string $template_slug ): WP_Block_Template|null
Parameters:
$template_slug(string) – Template slug (without namespace)
Returns: (WP_Block_Template|null) – Registered template or null
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
$template = $registry->get_by_slug( 'product-showcase' );
get_by_query()
Retrieves registered templates matching a query.
public function get_by_query( array $query = array() ): WP_Block_Template[]
Parameters:
$query(array) – Query arguments:slug__in(string[]) – Slugs to includeslug__not_in(string[]) – Slugs to excludepost_type(string) – Filter by post type
Returns: (WP_Block_Template[]) – Matching templates
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
// Get templates for 'product' post type
$product_templates = $registry->get_by_query( array(
'post_type' => 'product',
) );
// Get specific templates
$templates = $registry->get_by_query( array(
'slug__in' => array( 'single', 'archive' ),
) );
// Exclude certain templates
$templates = $registry->get_by_query( array(
'slug__not_in' => array( 'index' ),
) );
get_all_registered()
Retrieves all registered templates.
public function get_all_registered(): WP_Block_Template[]
Returns: (WP_Block_Template[]) – Associative array of templates
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
$all_templates = $registry->get_all_registered();
foreach ( $all_templates as $name => $template ) {
echo "$name: {$template->title}n";
}
is_registered()
Checks if a template is registered.
public function is_registered( string|null $template_name ): bool
Parameters:
$template_name(string|null) – Template name
Returns: (bool) – True if registered
Since: 6.7.0
Example:
$registry = WP_Block_Templates_Registry::get_instance();
if ( ! $registry->is_registered( 'my-plugin//custom' ) ) {
$registry->register( 'my-plugin//custom', array(
'title' => 'Custom Template',
'content' => '<!-- wp:paragraph --><p>Custom</p><!-- /wp:paragraph -->',
) );
}
Usage Examples
Complete Plugin Template Registration
add_action( 'init', function() {
$registry = WP_Block_Templates_Registry::get_instance();
// Register a landing page template
$registry->register( 'my-plugin//landing-page', array(
'title' => __( 'Landing Page', 'my-plugin' ),
'description' => __( 'A full-width landing page template', 'my-plugin' ),
'post_types' => array( 'page' ),
'content' => '
<!-- wp:cover {"minHeight":500,"align":"full"} -->
<div class="wp-block-cover alignfull">
<!-- wp:heading {"textAlign":"center","level":1} -->
<h1 class="has-text-align-center">Welcome</h1>
<!-- /wp:heading -->
</div>
<!-- /wp:cover -->
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:post-content /-->
</div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer"} /-->
',
) );
// Register a portfolio template
$registry->register( 'my-plugin//portfolio', array(
'title' => __( 'Portfolio', 'my-plugin' ),
'description' => __( 'Grid layout for portfolio items', 'my-plugin' ),
'post_types' => array( 'portfolio' ),
'content' => '
<!-- wp:template-part {"slug":"header"} /-->
<!-- wp:query {"queryId":1,"query":{"postType":"portfolio"}} -->
<div class="wp-block-query">
<!-- wp:post-template {"layout":{"type":"grid","columnCount":3}} -->
<!-- wp:post-featured-image /-->
<!-- wp:post-title /-->
<!-- /wp:post-template -->
</div>
<!-- /wp:query -->
<!-- wp:template-part {"slug":"footer"} /-->
',
) );
} );
Template Resulting Object
When registered, the template has these properties set:
$template->id // 'twentytwentyfour//landing-page' (uses active theme)
$template->theme // 'twentytwentyfour'
$template->plugin // 'my-plugin'
$template->slug // 'landing-page'
$template->type // 'wp_template'
$template->source // 'plugin'
$template->origin // 'plugin'
$template->status // 'publish'
$template->is_custom // false (if matches default type)
Checking Template Availability
add_action( 'admin_init', function() {
$registry = WP_Block_Templates_Registry::get_instance();
// Check before registering
if ( $registry->is_registered( 'my-plugin//landing-page' ) ) {
return; // Already registered
}
// Get all templates for a post type
$product_templates = $registry->get_by_query( array(
'post_type' => 'product',
) );
if ( empty( $product_templates ) ) {
// Register default product template
}
} );
Cleanup on Deactivation
register_deactivation_hook( __FILE__, function() {
$registry = WP_Block_Templates_Registry::get_instance();
$my_templates = array(
'my-plugin//landing-page',
'my-plugin//portfolio',
);
foreach ( $my_templates as $template_name ) {
if ( $registry->is_registered( $template_name ) ) {
$registry->unregister( $template_name );
}
}
} );