Skip to content

Instantly share code, notes, and snippets.

@thierrypigot
Created November 6, 2025 10:20
Show Gist options
  • Save thierrypigot/6eebc1b52203dd188b9d71e45c44baef to your computer and use it in GitHub Desktop.
Save thierrypigot/6eebc1b52203dd188b9d71e45c44baef to your computer and use it in GitHub Desktop.
Change the template used for singleposts based on their category, switching to a specific custom FSE (Full Site Editing) template when applicable. WordPress
<?php
/**
* Change the template used for single posts based on their category,
* switching to a specific custom FSE (Full Site Editing) template when applicable.
*
* Uses the `single_template_hierarchy` filter to insert the custom template
* at the top of the hierarchy when the post belongs to the target category.
*
* This method works:
* - On the front end (normal post display)
* - In the Site Editor (edit/preview mode)
*
* WordPress automatically looks for FSE templates in the hierarchy via `resolve_block_template()`.
*
* ---
* CONTEXT & EXAMPLE
* ---
* This snippet demonstrates how to dynamically assign a Full Site Editing template
* for single posts belonging to a specific category.
*
* Example:
* - Target category: “Actualités”
* - Category ID: 3
* - Category slug: `actualites`
* - Custom FSE template: `Single actualites`
* - Custom FSE template slug: `wp-custom-template-single-actualites`
*
* When a post belongs to this category, WordPress will use the
* `wp-custom-template-single-actualites` block template
* (defined in the Site Editor or in the theme’s `wp_template` post type).
*
* For all other posts, the default single template hierarchy is preserved.
*
* ---
* @param array $templates The current template hierarchy.
* @return array The modified hierarchy with the category-specific custom template added first.
*
* @author Thierry Pigot - www.wearewp.pro
* @license MIT
*/
function twentytwentyfive_child_change_single_template( $templates ) {
// Make sure this is indeed a single template hierarchy.
// The first element should be 'single' or start with 'single-'.
if ( empty( $templates ) || ( ! str_starts_with( $templates[0], 'single' ) && 'singular' !== $templates[0] ) ) {
return $templates;
}
// Retrieve the current post (works both on the front end and inside the Site Editor via REST API).
$current_post = null;
// First, try to get it with get_queried_object() (front end).
if ( is_singular( 'post' ) ) {
$current_post = get_queried_object();
}
// If we're in the Site Editor, try to get the post from the REST request.
if ( ! $current_post && isset( $_GET['postId'] ) && is_numeric( $_GET['postId'] ) ) {
$current_post = get_post( (int) $_GET['postId'] );
}
// If we still don't have a post, try to infer it from the slug.
if ( ! $current_post && ! empty( $templates[0] ) && str_starts_with( $templates[0], 'single-post-' ) ) {
// The slug is like 'single-post-{slug}', so let's try to get the post from that.
$post_slug = str_replace( 'single-post-', '', $templates[0] );
$current_post = get_page_by_path( $post_slug, OBJECT, 'post' );
}
// If no post was found, do nothing.
if ( ! $current_post || ! isset( $current_post->ID ) || 'post' !== $current_post->post_type ) {
return $templates;
}
// Check if the post belongs to the "Actualités" category (ID: 3).
// You can use either the ID or the slug.
if ( ! has_category( 3, $current_post->ID ) && ! has_category( 'actualites', $current_post->ID ) ) {
return $templates;
}
// Slug of the custom FSE template (without the 'wp_template/' prefix).
// Example: 'wp-custom-template-single-actualites' as found in the editor URL.
$custom_template_slug = 'wp-custom-template-single-actualites';
// Check if the custom template exists before adding it.
$theme_slug = get_stylesheet();
$template_id = $theme_slug . '//' . $custom_template_slug;
$custom_template = get_block_template( $template_id, 'wp_template' );
// If the template exists, prepend it to the hierarchy.
if ( $custom_template && ! empty( $custom_template->content ) ) {
array_unshift( $templates, $custom_template_slug );
}
return $templates;
}
add_filter( 'single_template_hierarchy', 'twentytwentyfive_child_change_single_template', 10, 1 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment