La función get_template_part en WordPress

Publicada en WordPress.

Una vez leí que la mejor manera de aprender a programar es leyendo el código que otros han escrito. A fin de cuentas, la mayor parte del tiempo que vas a emplear como desarrollador será, probablemente, repasando, puliendo y arreglando código que tú u otro desarrollador escribisteis en el pasado. Precisamente por eso me gusta tanto el software libre y al código abierto: nos permite ver las entrañas de las plataformas que usamos y aprender con ellas.

Si te interesa el mundillo WordPress (e imagino que así es, porque sino, ¿qué haces leyéndome?), echar un vistazo al código fuente del núcleo de WordPress o a Gutenberg son dos formas muy buenas de familiarizarte con el desarrollo en PHP de un backend y en JavaScript y React para el frontend.

Desde que salió Gutenberg, nos hemos centrado bastante en contarte lo que hemos aprendido sobre desarrollo en frontend. Así, por ejemplo, hicimos una serie de entradas donde te enseñábamos las bases de React, vimos cómo reaprovechar componentes, te explicamos cómo extender Gutenberg o discutimos novedades de JavaScript para escribir mejor código fuente.

Pues bien, hoy vamos a cambiar un poco la dinámica de los últimos meses y vamos a volver a centrarnos en el núcleo de WordPress. ¿Por qué? No sé, quizás porque el anuncio del próximo tema Twenty Twenty-One que salió hace unos días es la excusa perfecta para hacerlo ? . En concreto, vamos a introducir uno de los elementos más importantes a la hora de crear temas en WordPress: la función get_template_part.

Oso panda asustado al usar un ordenador
No sufras, que iremos poco a poco.

Los temas en WordPress

Antes de centrarnos en una función en concreto, es importante entender a grandes rasgos cómo funcionan los temas de WordPress a día de hoy. Básicamente, un tema es una colección de ficheros que define la estructura HTML y los estilos CSS que tendrá nuestra web cuando la veamos a través del navegador.

Si piensas en el esqueleto de una página web cualquiera, verás que siempre se repite el mismo patrón:

  • Empezamos abriendo las etiquetas html y head, donde metemos los scripts, estilos y meta etiquetas que nos interesan.
  • A continuación cerramos head y empezamos con el body, que es la parte donde estructuramos el contenido que ve el usuario
    • Normalmente, el cuerpo de una página incluye una cabecera con el logo de la web, un menú, etc.
    • A continuación viene el contenido en sí, que puede ser una página, un artículo del blog, una lista de entradas, el resultado de una búsqueda, etc.
    • Finalmente, se suele cerrar con un pie de página.
  • Y cuando ya hemos renderizado toda la página, cerramos las etiquetas body y html.

Si te fijas, da la sensación que toda página web sigue más o menos una estructura parecida. De hecho, dado un tema cualquiera, hay una parte que, en general, es común a toda la web (cabecera, menú, pie de página…) y otra que depende del tipo de contenido concreto que estamos viendo (una entrada, una búsqueda, un producto de WooCommerce, etc).

Como a los programadores no nos gusta repetir código y somos gente (en general) organizada, los tema de WordPress siguen una estructura de ficheros muy pautada. En esta entrada que escribí hace unos meses tienes una buena explicación de los diferentes ficheros que hay en un tema, pero quédate con que hay:

  • una hoja de estilos: style.css,
  • un fichero header.php para «abrir» la página web (esto es, meter la etiqueta head y, normalmente, la parte inicial del body común a todas las páginas),
  • otro fichero footer.php que «cierra» la web (metiendo el pie de página común a todas las páginas y cerrando las etiquetas body y html) y
  • un montón de ficheros adicionales para los diferentes tipos de contenido que queremos poder pintar.

¿Qué es y para qué sirve la función get_template_part?

Lo primero que debes hacer cuando te encuentras con una nueva función es lo contrario a lo que haces cuando tu padre te pide que le ayudes a programar su nuevo robot aspirador: leer la documentación:

get_template_part ofrece un mecanismo sencillo que permite a los temas sobrescribir partes reutilizables de un tema.

Se encarga de añadir la plantilla parcial especificada en el parámetro $slug. Si el tema no dispone de un fichero {slug}.php, entonces no incluye nada.

Internamente usa require (en lugar de require_once), con lo que es posible usar la misma plantilla parcial múltiples veces.

En cuanto al parámetro $name, si el fichero que quieres cargar es, por ejemplo, {slug}-special.php, entonces pasa "special" como segundo parámetro.

Aviso: cuando get_template_part falla, lo hace de forma silenciosa.

Documentación de get_template_part en WordPress.org

¿Has visto? En menos de un minuto hemos conseguido toda la información que nos interesa. Ahora ya sabemos que esta función sirve para crear «partes reutilizables» en un tema (con lo cual evitamos duplicar código) y lo hace de tal forma que un tema hijo las puede adaptar. También tenemos información sobre sus parámetros, su funcionamiento interno (usa require) y qué podemos esperar de ella (puede «fallar» sin dar problemas).

Niño contento

Por desgracia, lo mismo aún no tenemos claro qué son los ficheros estos {slug}.php y {slug}-special.php de los que nos habla… ¿Qué son? ¿Dónde van? ¿Qué contienen? ¿Qué hacen? Muchas preguntas difíciles de responder viendo únicamente la documentación, así que es hora de saltar a los ejemplos.

Cómo crear plantillas parciales en nuestro tema

Vamos a echar un vistazo al tema Twenty Twenty-One para descubrir si está usando estas «plantillas parciales» y, si lo hace, cómo las usa y qué pinta tienen.

Si leíste mi entrada sobre la jerarquía de ficheros de un tema WordPress, sabrás que «index.php es la plantilla por defecto de nuestro tema. Sirve para renderizar cualquier contenido de nuestra web, siempre que dicho contenido no tenga una plantilla específica diseñada para él». Como se trata de una plantilla por defecto, creo que es una buena idea empezar por ahí. Este es el contenido de index.php en el tema Twenty Twenty-One:

get_header();
if ( have_posts() ) {
  // Load posts loop.
  while ( have_posts() ) {
    the_post();
    get_template_part( 'template-parts/content/content' );
  }
  // Previous/next page navigation.
  twenty_twenty_one_the_posts_navigation();
} else {
  // If no content, include the "No posts found" template.
  get_template_part( 'template-parts/content/content-none' );
}
get_footer();

Como ves, tenemos todas las partes que habíamos comentado anteriormente:

  • Añadimos la cabecera de la web con get_header.
  • Pintamos el contenido en sí.
  • Cerramos la página con get_footer.

Lo interesante aquí, obviamente, está en la parte central de index.php. En concreto, vemos que tenemos un pequeño control para saber si estamos viendo o no algún contenido válido (función have_posts del Loop de WordPress) y, según si tenemos o no, cargamos una plantilla parcial (…/content) y otra ( …/content-none).

Si ahora echamos un vistazo a la plantilla parcial content.php, veremos (más o menos) lo siguiente:

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
  <header class="entry-header alignwide">
    …
    the_title( … );
    …
  </header>
  <div class="entry-content">
    <?php
    the_content( … );
    wp_link_pages( … );
    ?>
  </div>
  <footer class="entry-footer default-max-width">
    <?php twenty_twenty_one_entry_meta_footer(); ?>
  </footer>
  …
</article>

es decir, se trata de una pequeña plantilla diseñada para renderizar un contenido genérico de WordPress como puede ser, por ejemplo, una entrada del blog. Fíjate que el esqueleto HTML resultante no es más que una etiqueta article con un título, el contenido y un footer. El contenido en sí lo saca, ¿cómo no?, usando los template tags de WordPress (de los que podemos hablar en el futuro si quieres).

Ventajas de usar la API de WordPress

Aunque no conocieras todas las funciones de que dispones para montar un tema (como, por ejemplo, get_header, get_footer o la estrella de hoy, get_template_part), estoy bastante seguro de que habrías optado por organizar tu tema de una forma similar a como lo hace WordPress. A fin de cuentas, parece bastante lógico crear una plantilla para la cabecera, otra para el pie de página, otra para el contenido… y luego tener algo que lo empaquete todo. De haberlo hecho, es probable que tu fichero index.php fuera parecido a esto:

require_once 'header.php';
if ( have_posts() ) {
  // Load posts loop.
  while ( have_posts() ) {
    the_post();
    require 'template-parts/content.php';
  }
  // Previous/next page navigation.
  twenty_twenty_one_the_posts_navigation();
} else {
  // If no content, include the "No posts found" template.
  require 'template-parts/content-none.php';
}
require_once 'footer.php';

el cual se parece muchísimo al que tenemos en el tema Twenty Twenty-One. Con lo que, llegados a este punto, puedes preguntarte: ¿qué gano usando funciones específicas de WordPress? ¿Acaso no es lo mismo usar directamente un require de PHP, especialmente si tenemos en cuenta que, según la documentación de WordPress, estas funciones auxiliares «internamente también usan require»?

El principal motivo es el que mencionan en la propia documentación: si estás creando un tema hijo y usas get_template_part, WordPress se encargará de buscar la plantilla en el hijo y, si no está, usará la del padre. Esto, que parece una tontería, simplifica mucho el proceso de creación de temas hijo, puesto que únicamente deberás redefinir aquellas plantillas parciales que quieres adaptar; las demás puedes dejarlas de lado.

¡Pero eso no es todo! Las funciones de WordPress suelen estar plagadas de filtros y acciones que permiten adaptar el resultado final. Por ejemplo, si miramos cómo es internamente la función get_template_part en el fichero wp-includes/general-template.php:

function get_template_part( … ) {
  do_action( "get_template_part_{$slug}", … );
  …
  do_action( 'get_template_part', … );
  if ( ! locate_template( … ) ) {
    return false;
  }
}

vemos que tenemos un par de acciones a las que podemos engancharnos desde un plugin para realizar tareas adicionales durante la carga de una plantilla parcial.

Y si seguimos tirando del hilo con el objetivo de aprender, podemos ver cómo está implementada la función que se usa internamente (locate_template):

function locate_template( $template_names, … ) {
  $located = '';
  foreach ( $template_names as $name ) {
    if ( file_exists( STYLESHEETPATH . "/$name" ) ) {
      $located = …; // in child theme
      break;
    } else if ( file_exists( STYLESHEETPATH . "/$name" ) ) {
      $located = …; // in parent theme
      break;
    } else {
      …
    }
  }
  if ( $located ) {
    load_template( $located, $require_once, $args );
  }
  return $located;
}

con lo que en seguida descubres que WordPress hace un montón de cosas por ti entre bastidores.

Espero que la entrada de hoy te haya ayudado a entender un poco mejor cómo funcionan los temas de WordPress. También confío en que haya sido un buen ejemplo de cómo aprender sobre WordPress leyendo su documentación y, especialmente, cotilleando sin miedo su código fuente, tirando del hilo tanto como sea necesario. Y si te ha gustado, ya sabes: compártela con tus amigos y déjanos un comentario.

Imagen destacada de Joshua Sortino en Unsplash.

Deja una respuesta

No publicaremos tu correo electrónico. Los campos obligatorios están marcados con: •

He leído y acepto la Política de privacidad de Nelio Software

Al marcar la casilla de aceptación estás dando tu legítimo consentimiento para que tu información personal se almacene en SiteGround y sea usada por Nelio Software con el propósito único de publicar aquí este comentario. Contáctanos para corregir, limitar, eliminar o acceder a tu información.