Odio ser el portador de malas noticias pero WordPress codifica la funcionalidad de la Plantilla de Página a la "página" tipo de publicación , al menos en v3.0 ( eso podría cambiar en las versiones futuras, pero no hay una iniciativa específica de la que deba cambiarlo todavía. Por lo tanto, esta es una de las pocas veces que estoy luchando para descubrir cómo sortear algo sin hackear el núcleo.)
La solución que he encontrado es básicamente copiar el código relevante del núcleo de WordPress y modificarlo según nuestras necesidades. Aquí están los pasos (los números de línea son de v3.0.1):
Copie la función page_attributes_meta_box()
de la línea 535 de /wp-admin/includes/meta-boxes.php
y modifíquela para adaptarla.
Codifique un gancho add_meta_boxes
para agregar el metabox creado en el # 1.
Copie la función get_page_templates()
de la línea 166 de /wp-admin/includes/theme.php
y modificar para adaptarse.
Copie la función page_template_dropdown()
de la línea 2550 de /wp-admin/includes/template.php
y modifíquela para adaptarla.
Agrega una plantilla de publicación a tu tema.
Codifique un gancho save_post
para habilitar el almacenamiento del nombre del archivo de la plantilla de publicación al guardar.
Codifique un gancho single_template
para habilitar la carga de la plantilla de publicaciones para las publicaciones asociadas.
¡Ahora en marcha!
1. Copie la función page_attributes_meta_box()
Como nuestro primer paso, necesita copiar la función page_attributes_meta_box()
de la línea 535 de /wp-admin/includes/meta-boxes.php
y he elegido cambiarle el nombre a post_template_meta_box()
. Como solo pidió plantillas de página, omití el código para especificar una publicación principal y para especificar el orden, lo que hace que el código sea mucho más sencillo. También opté por usar postmeta para esto en lugar de intentar reutilizar la propiedad de objeto page_template
para evitar posibles incompatibilidades causadas por el acoplamiento involuntario. Así que aquí está el código:
function post_template_meta_box($post) {
if ( 'post' == $post->post_type && 0 != count( get_post_templates() ) ) {
$template = get_post_meta($post->ID,'_post_template',true);
?>
<label class="screen-reader-text" for="post_template"><?php _e('Post Template') ?></label><select name="post_template" id="post_template">
<option value='default'><?php _e('Default Template'); ?></option>
<?php post_template_dropdown($template); ?>
</select>
<?php
} ?>
<?php
}
2. Codifique un gancho add_meta_boxes
El siguiente paso es agregar el metabox usando el add_meta_boxes
hook:
add_action('add_meta_boxes','add_post_template_metabox');
function add_post_template_metabox() {
add_meta_box('postparentdiv', __('Post Template'), 'post_template_meta_box', 'post', 'side', 'core');
}
3. Copie la función get_page_templates()
Supuse que solo tendría sentido diferenciar entre plantillas de página y plantilla de publicación, por lo tanto, la necesidad de una función get_post_templates()
basada en get_page_templates()
de la línea 166 de /wp-admin/includes/theme.php
. Pero en lugar de usar el marcador Template Name:
, las plantillas de página que usan esta función usan un marcador Post Template:
en lugar de lo que puede ver a continuación.
También filtré la inspección de functions.php
(no estoy seguro de cómo get_page_templates()
funcionó correctamente sin eso, ¡pero lo que sea!) Y lo único que queda es cambiar las referencias a la palabra page
a post
para facilitar la lectura en el futuro:
function get_post_templates() {
$themes = get_themes();
$theme = get_current_theme();
$templates = $themes[$theme]['Template Files'];
$post_templates = array();
if ( is_array( $templates ) ) {
$base = array( trailingslashit(get_template_directory()), trailingslashit(get_stylesheet_directory()) );
foreach ( $templates as $template ) {
$basename = str_replace($base, '', $template);
if ($basename != 'functions.php') {
// don't allow template files in subdirectories
if ( false !== strpos($basename, '/') )
continue;
$template_data = implode( '', file( $template ));
$name = '';
if ( preg_match( '|Post Template:(.*)$|mi', $template_data, $name ) )
$name = _cleanup_header_comment($name[1]);
if ( !empty( $name ) ) {
$post_templates[trim( $name )] = $basename;
}
}
}
}
return $post_templates;
}
4. Copie la función page_template_dropdown()
De forma similar, copie page_template_dropdown()
de la línea 2550 de /wp-admin/includes/template.php
para crear post_template_dropdown()
y simplemente cámbielo para llamar a get_post_templates()
en su lugar:
function post_template_dropdown( $default = '' ) {
$templates = get_post_templates();
ksort( $templates );
foreach (array_keys( $templates ) as $template )
: if ( $default == $templates[$template] )
$selected = " selected='selected'";
else
$selected = '';
echo "\n\t<option value='".$templates[$template]."' $selected>$template</option>";
endforeach;
}
5. Añadir una plantilla de publicación
El siguiente paso es agregar una plantilla de publicación para la prueba. Usando el marcador Post Template:
mencionado en el paso # 3, copie single.php
de su tema en single-test.php
y agregue el siguiente encabezado de comentario ( asegúrese de modificar algo en single-test.php
para que pueda saber que se está cargando en lugar de single.php
) :
/**
* Post Template: My Test Template
*/
Una vez que haya realizado los pasos del 1 al 5, podrá ver su metabox "Plantillas de publicación" en su página de editor de publicación:

6.Codifiqueunganchosave_post
Ahoraquetieneeleditoralcuadrado,debeguardarelnombredearchivodesuplantilladepáginaenpostmetacuandoelusuariohagaclicen"Publicar". Aquí está el código para eso:
add_action('save_post','save_post_template',10,2);
function save_post_template($post_id,$post) {
if ($post->post_type=='post' && !empty($_POST['post_template']))
update_post_meta($post->ID,'_post_template',$_POST['post_template']);
}
7. Codifique un gancho single_template
Y, por último, necesitas que WordPress use tus nuevas plantillas de publicaciones. Para hacerlo, conecte single_template
y devuelva el nombre de la plantilla deseada para aquellas publicaciones que hayan tenido una asignada:
add_filter('single_template','get_post_template_for_template_loader');
function get_post_template_for_template_loader($template) {
global $wp_query;
$post = $wp_query->get_queried_object();
if ($post) {
$post_template = get_post_meta($post->ID,'_post_template',true);
if (!empty($post_template) && $post_template!='default')
$template = get_stylesheet_directory() . "/{$post_template}";
}
return $template;
}
¡Y eso es todo!
NOTA de que no consideré Tipos de publicaciones personalizadas , solo post_type=='post'
. En mi opinión, abordar tipos de publicaciones personalizados requeriría diferenciar los diferentes tipos de publicaciones y, aunque no es demasiado difícil, no lo intenté aquí.