¿Plantillas de Tipos de Entrada Personalizados desde la Carpeta del Plugin?

16 may 2011, 16:16:45
Vistas: 53.9K
Votos: 82

Me gustaría ofrecer mi tipo de entrada personalizado como un Plugin, para que la gente pueda usarlo sin tener que tocar la carpeta de su tema. Pero las plantillas de tipos de entrada personalizados -- como single-movies.php -- residen en la carpeta del tema. ¿Hay alguna manera de hacer que WordPress busque el archivo single-movies.php en la carpeta del plugin? ¿Enlazando una función en la Jerarquía de Filtros? ¿O usando get_template_directory(); ?

0
Todas las respuestas a la pregunta 8
7
121

Puedes usar el hook de filtro single_template.

/* Filtrar el single_template con nuestra función personalizada */
add_filter('single_template', 'my_custom_template');

function my_custom_template($single) {

    global $post;

    /* Verifica la plantilla single por tipo de post */
    if ( $post->post_type == 'NOMBRE DEL TIPO DE POST' ) {
        if ( file_exists( RUTA_DEL_PLUGIN . '/Archivo_Personalizado.php' ) ) {
            return RUTA_DEL_PLUGIN . '/Archivo_Personalizado.php';
        }
    }

    return $single;

}
16 may 2011 16:41:53
Comentarios

Es una respuesta increíble. Por favor comparte dónde puedo obtener todos los hooks de plantilla disponibles como single_template.

Gowri Gowri
2 may 2013 21:18:00

@gowri El filtro es llamado por la función get_query_template(). Es un hook variable, por lo que la primera parte {$type}_template cambia dependiendo del parámetro que se pase a esa función. Mira wp-includes/template.php para algunos ejemplos comunes

shea shea
7 may 2013 12:42:24

Este tutorial cubre el hook single_template con una buena explicación. Una vez que entiendas los hooks, el comentario de @shea sugiere un enfoque más simple que la respuesta de @Bainternet, usando add_filter( 'single-movies_template', 'my_custom_template' ); como en el tutorial enlazado. (Esta pregunta está cerrada a nuevas respuestas, así que no puedo agregarla por sí sola.)

Greg Perham Greg Perham
26 sept 2017 07:34:29

Podrías reemplazar PLUGIN_PATH con plugin_dir_path( __FILE__ ) y luego eliminar la primera barra del nombre de tu archivo. La ruta completa se vería algo así: return plugin_dir_path( __FILE__ ) . 'Custom_File.php';

Frits Frits
13 feb 2018 08:49:06

Podría ser que PLUGIN_PATH ahora se llame WP_PLUGIN_DIR.

Hans Dash Hans Dash
26 mar 2019 18:19:43

PLUGIN_PATH generó un error, aquí hay una publicación excelente que muestra cómo hacer esto y funcionó para mí inmediatamente: https://wpsites.net/free-tutorials/load-single-template-from-plugin-for-different-post-types/

Nathan Nathan
2 may 2019 23:19:24

¿hay un filtro para solo un tipo de publicación personalizada?

v3nt v3nt
6 sept 2019 11:46:02
Mostrar los 2 comentarios restantes
3
40

Respuesta actualizada

Versión más limpia y corta.

function load_movie_template( $template ) {
    global $post;

    if ( 'movie' === $post->post_type && locate_template( array( 'single-movie.php' ) ) !== $template ) {
        /*
         * Esto es un post de tipo 'movie'
         * Y no se encuentra una plantilla 'single movie' en
         * los directorios del tema o tema hijo, así que cargarla
         * desde el directorio de nuestro plugin.
         */
        return plugin_dir_path( __FILE__ ) . 'single-movie.php';
    }

    return $template;
}

add_filter( 'single_template', 'load_movie_template' );

Respuesta anterior

Añadida una comprobación para una plantilla específica de tipo de post personalizado en la carpeta del tema a la respuesta de @Brainternet.

function load_cpt_template($template) {
    global $post;

    // ¿Es este un post de tipo "my-custom-post-type"?
    if ($post->post_type == "my-custom-post-type"){

        // Ruta de tu plugin
        $plugin_path = plugin_dir_path( __FILE__ );

        // Nombre de la plantilla single para el tipo de post personalizado
        $template_name = 'single-my-custom-post-type.php';

        // ¿Existe una plantilla single específica para mi tipo de post en la carpeta del tema? ¿O tampoco existe en mi plugin?
        if($template === get_stylesheet_directory() . '/' . $template_name
            || !file_exists($plugin_path . $template_name)) {

            // Entonces devuelve "single.php" o "single-my-custom-post-type.php" del directorio del tema.
            return $template;
        }

        // Si no, devuelve la plantilla del tipo de post personalizado de mi plugin.
        return $plugin_path . $template_name;
    }

    // Esto no es mi tipo de post personalizado, no hacer nada con $template
    return $template;
}
add_filter('single_template', 'load_cpt_template');

Ahora puedes permitir que los usuarios del plugin copien la plantilla desde tu plugin a su tema para sobrescribirla.

Con este ejemplo, las plantillas deben estar en el directorio raíz tanto del plugin como del tema.

15 ene 2016 11:45:36
Comentarios

Usar locate_template en lugar de get_stylesheet_directory me parece la opción más limpia (encontrado aquí: http://code.tutsplus.com/tutorials/a-guide-to-wordpress-custom-post-types-creation-display-and-meta-boxes--wp-27645).

Felix Felix
14 jun 2016 21:11:35

La respuesta actualizada no funcionó, la respuesta aceptada (o tu respuesta antigua) sí funciona.

Edward Edward
29 mar 2018 17:43:43

Tienes razón, @Edward, esa fue una actualización terrible. Lo actualicé nuevamente con la sugerencia de Felix. Esta vez también probé el código antes de publicarlo :)

campsjos campsjos
3 abr 2018 18:40:46
0

Me gustaría señalar que cuando estás utilizando el método de filtro para esto, es extremadamente importante priorizar el filtro de la siguiente manera:

add_filter('single_template', 'my_custom_template', 99);

Si no haces esto, a veces WordPress intentará volver a verificar después de este filtro. Me estuve arrancando los pelos por esto durante como 2 horas.

14 dic 2016 18:33:50
0

En mis propios plugins suelo utilizar locate_template() lo que permite anular la plantilla del plugin copiándola en el tema actual:

function templateInclude(string $template): string
{
    if (is_single() && get_query_var('post_type') === 'custom_post_type') {
        $templates = [
            'single-custom_post.php',
            'templates/single-custom_post.php'
        ];
        $template = locate_template($templates);
        if (!$template) {
            $template = __DIR__ . '/templates/single-custom_post.php';
        }
    }
    return $template;
}

add_filter('template_include', 'templateInclude');

Ahora el usuario puede anular la plantilla del plugin copiándola desde la carpeta del plugin templates/single-custom_post.php y colocándola directamente en la raíz o dentro de una carpeta templates en el tema activo.

Supongo que deberías poder usar el mismo enfoque cuando utilices el filtro single_template también.

16 dic 2021 21:38:20
0

Hay una forma mucho mejor de hacerlo que estoy usando para mis plugins.

Como @campsjos menciona aquí, en lugar de verificar la existencia del archivo, puedes verificar locate_template que buscará en el archivo de plantilla anulado por el tema. Lo cual es bastante obvio.

function my_plugin_templates() {
    if (is_singular('movie')) {
        if (file_exists($this->template_dir . 'single-movie.php')) {
            return $this->template_dir . 'single-movie.php';
        }
    }
}

Usa el filtro template_include para cargar el código anterior.

add_filter('template_include' , 'my_plugin_templates');
1 ago 2019 08:39:55
0

gracias a esta página pude resolver la misma pregunta para mí.

Como referencia, esto es con lo que terminé:

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';
  return get_post_type() === 'myposttype' && file_exists($myposttype_template) ? $myposttype_template : $single_template;
}
add_filter('single_template', 'pluginName_myposttype_single_template');

el hook de filtro {$type}_template no funcionó para mí

function pluginName_myposttype_single_template($single_template) {
  $myposttype_template = PLUGIN_DIR . 'templates/single-myposttype.php';

  if ( file_exists($myposttype_template) ) {
    $single_template = $myposttype_template;
  }
  return $single_template;
}
add_filter('single-myposttype_template', 'pluginName_myposttype_single_template');
20 oct 2019 02:21:03
0

Esto funcionó para mí, por favor pruébalo, gracias.
Las plantillas se cargan en el archivo cpt, que se encuentra en
custom_plugin -> app -> cpt -> cpt_article.php
La plantilla está ubicada en
custom_plugin -> app -> templates

add_filter( 'single_template', 'load_my_custom_template', 99, 1 );
 function load_custom_templates($single_template) {
   global $post;
   if ($post->post_type == 'article' ) {
   $single_template = trailingslashit( plugin_dir_path( __FILE__ ) .'app/templates' ).'single_article.php';
  }
   return $single_template;
}
11 jul 2020 02:59:54
2
-2

La respuesta anterior es excelente, pero verificando la variable $single permite que la plantilla sobrescriba una plantilla si esta es proporcionada por el tema/child theme.

/* Filtra el single_template con nuestra función personalizada */
add_filter('single_template', 'your_cpt_custom_template');

function your_cpt_custom_template( $single ) {
    global $wp_query, $post;
    /* Verifica la plantilla individual por tipo de publicación */
    if ( !$single && $post->post_type == 'cpt' ) {
        if( file_exists( plugin_dir_path( __FILE__ ) . 'single-cpt.php' ) )
            return plugin_dir_path( __FILE__ ) . 'single-cpt.php';
    }
    return $single;
}
19 oct 2015 19:47:59
Comentarios

Esto no verifica si single-cpt.php está presente en un child theme o en el tema principal. Solo verifica contra single.php que siempre estará presente en cualquier tema.

newpoison newpoison
28 oct 2015 22:01:47

Así es, cuando escribí esto estaba usando un tema muy básico, ¡tiene que haber una mejor manera!

DigitalDesignDj DigitalDesignDj
20 nov 2015 23:19:20