Pasando variables a través de locate_template
Aunque tradicionalmente he usado include
o require
para mantener el código a largo plazo, he comenzado a usar get_template_part
y locate_template
ya que usar las funciones integradas de WordPress siempre es lo mejor.
Mi pregunta es: ¿se supone que debes poder pasar variables a través de los resultados de get_template_part
o locate_template
?
<?php
$var = get_option( 'my-custom-option' );
get_template_part( 'custom-template-part' );
?>
En el código anterior, la variable $var
debería imprimirse dentro de la plantilla personalizada, pero la variable no parece funcionar. ¿Me estoy perdiendo algo o este es el comportamiento esperado?
He descubierto que no se pasan las variables en el ejemplo anterior ni cuando se usa locate_template
<?php
locate_template( 'custom-template-part.php', true );
?>

Como MathSmath escribió, get_template() no soporta la reutilización de tus variables.
Pero locate_template() de hecho no realiza ninguna inclusión. Simplemente localiza un archivo para su inclusión.
Así que puedes hacer uso de include para que esto funcione justo como esperas:
include(locate_template('custom-template-part.php'));
$var
de tu ejemplo puede ser usado en la parte de la plantilla entonces.
Una pregunta relacionada con una explicación más técnica del ámbito de las variables y get_template(): Error al Enviar Formulario con get_template_part()

Buena observación. No me había dado cuenta de que locate_template() tiene un parámetro que te permite opcionalmente llamar a load_template() con los resultados (lo cual hace get_template_part), o simplemente devolverlos. Estoy revisando un proyecto actual para actualizar el código usando este enfoque... ¡gracias!

21676 aborda esto, pero no parece que vaya a ser incluido.

Quizás estoy equivocado pero: locate_template()
de hecho sí incluye, si el parámetro está configurado como true
-como en la pregunta. (el valor por defecto es false
, así que no copies la versión de la pregunta en la respuesta aceptada.) También podrías simplemente usar set_query_var('var', $var);
y usar tu get_template_part()
como siempre. De esa manera también tendrás las variables por defecto de WordPress accesibles dentro del archivo de plantilla, como mencionó @MathSmath.

Una solución elegante encontrada en el codex
Así que si estás iterando a través de posts personalizados, puedes hacer esto:
foreach ($custom_posts as $custom_post) {
set_query_var( 'my_post', $custom_post );
get_template_part( 'content', 'part' );
}
Y en esa plantilla en sí, automáticamente obtendrás una variable $my_post
.

Esta sería la respuesta correcta si el código de ejemplo respondiera a la pregunta. (Pasando opción, no el array completo de posts)

Yo también he tenido problemas con esto (al intentar hacer funcionar una consulta personalizada con una parte de plantilla). La respuesta corta es: no, la parte de plantilla no hereda automáticamente las variables personalizadas como lo haría un include normal.
Tanto get_template_part() como locate_template() terminan usando la función load_template() para cargar realmente el archivo (usando un require). Esta función globaliza las siguientes variables:
$posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID
Sin embargo, no hay otras variables disponibles desde dentro de la parte de plantilla. Supongo que como el require real está envuelto en una función, el ámbito cambia o algo así.
En cualquier caso, intentaría globalizar cualquier variable adicional que necesites pasar, y luego llamar a esas globales desde tu parte de plantilla.

Mi pequeño aporte para referencias futuras, una solución alternativa al menos en WordPress 3.5 es agregar la variable a $wp_query->query_vars
.
Yo necesitaba mi variable global _vk_errors
dentro de una parte de plantilla y simplemente hice $wp_query->query_vars['_vk_errors'] = $_vk_errors;
antes de llamar a get_template_part()
.

WordPress 5.5+
Se añadió el parámetro $args a locate_template
https://developer.wordpress.org/reference/functions/locate_template/
Pasar datos
$data = [
'foo' => 'Hola',
'bar' => ', WordPress 5.5',
];
locate_template('tu-plantilla.php', true, true, $data);
tu-plantilla.php
// manejar argumentos pasados mediante $args
echo $args['foo'] . $args['bar']; // "Hola, WordPress 5.5"
// o usar extract($args);
extract($args);
echo $foo . $bar; // "Hola, WordPress 5.5"
locate_template
utiliza load_template
, que desde la versión 5.5 también puede pasar argumentos adicionales a la plantilla.
https://developer.wordpress.org/reference/functions/load_template/
Lo mismo ocurre con todas las funciones de plantilla que usan locate_template
:
get_header
, get_footer
, get_sidebar
, get_template_part
.
https://developer.wordpress.org/reference/functions/get_header/ https://developer.wordpress.org/reference/functions/get_footer/ https://developer.wordpress.org/reference/functions/get_sidebar/ https://developer.wordpress.org/reference/functions/get_template_part/

Aquí está mi función simple que resuelve el problema de variables. Hace lo mismo que WordPress en la función get_template_part()
. Solo copia y pega en el archivo function.php
.
function getTemplatePart($slug = null, $name = null, array $params = array()) {
global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
// Ejecuta acción antes de cargar la plantilla
do_action("get_template_part_{$slug}", $slug, $name);
$templates = array();
if (isset($name))
$templates[] = "{$slug}-{$name}.php";
$templates[] = "{$slug}.php";
// Localiza el archivo de plantilla
$_template_file = locate_template($templates, false, false);
// Extrae variables de la consulta
if (is_array($wp_query->query_vars)) {
extract($wp_query->query_vars, EXTR_SKIP);
}
// Extrae parámetros personalizados
extract($params, EXTR_SKIP);
// Carga la plantilla
require($_template_file);
}
Ejemplo de uso en una plantilla:
$params = array(
'utm_source' => 'footer' // Parámetro personalizado
);
while ($posts->have_posts()) {
$posts->the_post();
// Carga la plantilla con parámetros
getTemplatePart('content', 'heighlight', $params);
}
En el archivo content-heighlight.php
estará accesible la variable con nombre $utm_source
y valor footer
.

Puedes simplemente envolver el get_template_part, almacenar un objeto modelo en una variable global y limpiarlo después. Así es como lo hemos estado haciendo en nuestros proyectos:
functions.php
$model = null; // esta es una variable global
function my_get_template_part($slug, $name = null, $templateModel = null) {
global $model;
$model = $templateModel; // establece la variable global con el objeto modelo proporcionado
get_template_part($slug,$name);
$model = null; // limpia la variable global
}
function get_model() {
global $model;
return $model;
}
Uso en la plantilla principal:
<?php my_get_template_part('template-parts/xxxx','xxx',array('test1'))?>
Accediendo al modelo proporcionado en el template-part:
<?php $model = get_model() ?>
De esta manera, no tienes que copiar y pegar la función original get_template_part a tu propia función en caso de que su implementación cambie más tarde por los desarrolladores de WordPress.
