Pasar una variable a get_template_part

55

El WP Codex dice hacer esto:

// You wish to make $my_var available to the template part at `content-part.php`
set_query_var( 'my_var', $my_var );
get_template_part( 'content', 'part' );

Pero, ¿cómo hago echo $my_vardentro de la parte de la plantilla? get_query_var($my_var)no funciona para mi

He visto toneladas de recomendaciones para usar en su locate_templatelugar. ¿Es esa la mejor manera de ir?

Florian
fuente
Tenía aproximadamente la misma pregunta y tengo que trabajar con set_query_vary get_query_var, sin embargo, esto era para el uso de los valores de una $argsmatriz que se pasa a una WP_Query. Puede ser útil para otras personas que comienzan a aprender esto.
lowtechsun

Respuestas:

53

A medida que las publicaciones configuran sus datos a través de the_post()(respectivamente a través de setup_postdata()) y, por lo tanto, son accesibles a través de la API ( get_the_ID()por ejemplo), supongamos que estamos recorriendo un conjunto de usuarios (ya que setup_userdata()llena las variables globales del usuario actualmente conectado y no está ' t útil para esta tarea) e intente mostrar metadatos por usuario:

<?php
get_header();

// etc.

// In the main template file
$users = new \WP_User_Query( [ ... ] );

foreach ( $users as $user )
{
    set_query_var( 'user_id', absint( $user->ID ) );
    get_template_part( 'template-parts/user', 'contact_methods' );
}

Luego, en nuestro wpse-theme/template-parts/user-contact_methods.phparchivo, necesitamos acceder a la ID de usuario:

<?php
/** @var int $user_id */
$some_meta = get_the_author_meta( 'some_meta', $user_id );
var_dump( $some_meta );

Eso es.

La explicación en realidad está exactamente por encima de la parte que citó en su pregunta:

Sin embargo, lo load_template()que se llama indirectamente por get_template_part()extractos de todas las WP_Queryvariables de consulta, dentro del alcance de la plantilla cargada.

La extract()función nativa de PHP "extrae" las variables (la global $wp_query->query_varspropiedad) y pone cada parte en su propia variable que tiene exactamente el mismo nombre que la clave. En otras palabras:

set_query_var( 'foo', 'bar' );

$GLOBALS['wp_query'] (object)
    -> query_vars (array)
        foo => bar (string 3)

extract( $wp_query->query_vars );

var_dump( $foo );
// Result:
(string 3) 'bar'
emperador
fuente
1
sigue funcionando muy bien
huraji
23

La hm_get_template_partfunción de humanmade es extremadamente buena en esto y la uso todo el tiempo.

Llama

hm_get_template_part( 'template_path', [ 'option' => 'value' ] );

y luego dentro de tu plantilla, usas

$template_args['option'];

para devolver el valor. Realiza el almacenamiento en caché y todo, aunque puede eliminarlo si lo desea.

Incluso puede devolver la plantilla representada como una cadena pasando 'return' => truea la matriz de clave / valor.

/**
 * Like get_template_part() put lets you pass args to the template file
 * Args are available in the tempalte as $template_args array
 * @param string filepart
 * @param mixed wp_args style argument list
 */
function hm_get_template_part( $file, $template_args = array(), $cache_args = array() ) {
    $template_args = wp_parse_args( $template_args );
    $cache_args = wp_parse_args( $cache_args );
    if ( $cache_args ) {
        foreach ( $template_args as $key => $value ) {
            if ( is_scalar( $value ) || is_array( $value ) ) {
                $cache_args[$key] = $value;
            } else if ( is_object( $value ) && method_exists( $value, 'get_id' ) ) {
                $cache_args[$key] = call_user_method( 'get_id', $value );
            }
        }
        if ( ( $cache = wp_cache_get( $file, serialize( $cache_args ) ) ) !== false ) {
            if ( ! empty( $template_args['return'] ) )
                return $cache;
            echo $cache;
            return;
        }
    }
    $file_handle = $file;
    do_action( 'start_operation', 'hm_template_part::' . $file_handle );
    if ( file_exists( get_stylesheet_directory() . '/' . $file . '.php' ) )
        $file = get_stylesheet_directory() . '/' . $file . '.php';
    elseif ( file_exists( get_template_directory() . '/' . $file . '.php' ) )
        $file = get_template_directory() . '/' . $file . '.php';
    ob_start();
    $return = require( $file );
    $data = ob_get_clean();
    do_action( 'end_operation', 'hm_template_part::' . $file_handle );
    if ( $cache_args ) {
        wp_cache_set( $file, $data, serialize( $cache_args ), 3600 );
    }
    if ( ! empty( $template_args['return'] ) )
        if ( $return === false )
            return false;
        else
            return $data;
    echo $data;
}
djb
fuente
¿Incluye 1300 líneas de código (desde github HM) al proyecto para pasar un parámetro a una plantilla? No puedo hacer esto en mi proyecto :(
Gediminas
11

Estaba mirando alrededor y he encontrado una variedad de respuestas. Parece a nivel nativo, Wordpress permite acceder a las variables en las partes de la Plantilla. Encontré que el uso de include junto con Locate_template permitió que el alcance de las variables fuera accesible en el archivo.

include(locate_template('your-template-name.php'));
Murray Chapman
fuente
El uso includeno pasará la comprobación de tema .
lowtechsun
¿Realmente necesitamos algo como el verificador W3C para WP Themes?
Fredy31
5
// you can use any value including objects.

set_query_var( 'var_name_to_be_used_later', 'Value to be retrieved later' );
//Basically set_query_var uses PHP extract() function  to do the magic.


then later in the template.
var_dump($var_name_to_be_used_later);
//will print "Value to be retrieved later"

Recomiendo leer sobre la función PHP Extract ().

Hugo R
fuente
2

Me encontré con este mismo problema en un proyecto en el que estoy trabajando actualmente. Decidí crear mi propio pequeño complemento que le permite pasar más explícitamente variables a get_template_part mediante el uso de una nueva función.

En caso de que le resulte útil, aquí está la página en GitHub: https://github.com/JolekPress/Get-Template-Part-With-Variables

Y aquí hay un ejemplo de cómo funcionaría:

$variables = [
    'name' => 'John',
    'class' => 'featuredAuthor',
];

jpr_get_template_part_with_vars('author', 'info', $variables);


// In author-info.php:
echo "
<div class='$class'>
    <span>$name</span>
</div>
";

// Would output:
<div class='featuredAuthor'>
    <span>John</span>
</div>
John O
fuente
1

Me gusta el complemento Pods y su función pods_view . Funciona de manera similar a la hm_get_template_partfunción mencionada en la respuesta de djb. Utilizo una función adicional ( findTemplateen el código a continuación) para buscar primero un archivo de plantilla en el tema actual, y si no lo encuentra, devuelve la plantilla con el mismo nombre en la /templatescarpeta de mi complemento . Esta es una idea aproximada de cómo estoy usando pods_viewmi plugin:

/**
 * Helper function to find a template
 */
function findTemplate($filename) {
  // Look first in the theme folder
  $template = locate_template($filename);
  if (!$template) {
    // Otherwise, use the file in our plugin's /templates folder
    $template = dirname(__FILE__) . '/templates/' . $filename;
  }
  return $template;
}

// Output the template 'template-name.php' from either the theme
// folder *or* our plugin's '/template' folder, passing two local
// variables to be available in the template file
pods_view(
  findTemplate('template-name.php'),
  array(
    'passed_variable' => $variable_to_pass,
    'another_variable' => $another_variable,
  )
);

pods_viewTambién es compatible con el almacenamiento en caché, pero no lo necesitaba para mis propósitos. Puede encontrar más información sobre los argumentos de la función en las páginas de documentación de Pods. Consulte las páginas para pods_view y Almacenamiento parcial de páginas y partes de plantillas inteligentes con pods .

Thirdender
fuente
1

Basado en la respuesta de @djb usando el código de humanmade.

Esta es una versión ligera de get_template_part que puede aceptar argumentos. De esta forma, las variables se definen localmente para esa plantilla. No hay necesidad de tener global, get_query_var, set_query_var.

/**
 * Like get_template_part() but lets you pass args to the template file
 * Args are available in the template as $args array.
 * Args can be passed in as url parameters, e.g 'key1=value1&key2=value2'.
 * Args can be passed in as an array, e.g. ['key1' => 'value1', 'key2' => 'value2']
 * Filepath is available in the template as $file string.
 * @param string      $slug The slug name for the generic template.
 * @param string|null $name The name of the specialized template.
 * @param array       $args The arguments passed to the template
 */

function _get_template_part( $slug, $name = null, $args = array() ) {
    if ( isset( $name ) && $name !== 'none' ) $slug = "{$slug}-{$name}.php";
    else $slug = "{$slug}.php";
    $dir = get_template_directory();
    $file = "{$dir}/{$slug}";

    ob_start();
    $args = wp_parse_args( $args );
    $slug = $dir = $name = null;
    require( $file );
    echo ob_get_clean();
}

Por ejemplo en cart.php:

<? php _get_template_part( 'components/items/apple', null, ['color' => 'red']); ?>

En apple.php:

<p>The apple color is: <?php echo $args['color']; ?></p>
Veedka
fuente
0

¿Qué tal esto?

render( 'template-parts/header/header', 'desktop', 
    array( 'user_id' => 555, 'struct' => array( 'test' => array( 1,2 ) ) )
);
function render ( $slug, $name, $arguments ) {

    if ( $arguments ) {
        foreach ( $arguments as $key => $value ) {
                ${$key} = $value;
        }
    }

$name = (string) $name;
if ( '' !== $name ) {
    $templates = "{$slug}-{$name}.php";
    } else {
        $templates = "{$slug}.php";
    }

    $path = get_template_directory() . '/' . $templates;
    if ( file_exists( $path ) ) {
        ob_start();
        require( $path);
        ob_get_clean();
    }
}

Mediante el uso ${$key}puede agregar las variables en el alcance de la función actual. Funciona para mí, rápido y fácil y no tiene fugas ni está almacenado en el alcance global.

Mattijs
fuente
0

Para aquellos que buscan una manera muy fácil de pasar variables, puede cambiar la función para incluir:

include (location_template ('YourTemplate.php', falso, falso));

Y luego podrá usar todas las variables que se definen antes de incluir la plantilla sin PASAR adicionalmente cada una para la plantilla.

Los créditos van a: https://mekshq.com/passing-variables-via-get_template_part-wordpress/

Gediminas
fuente