web-dev-qa-db-fra.com

Passer une variable à get_template_part

Le WP Codex dit pour faire ceci:

// 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' );

Mais comment puis-je echo $my_var dans la partie modèle? get_query_var($my_var) ne fonctionne pas pour moi.

J'ai vu des tonnes de recommandations pour utiliser locate_template à la place. Est-ce la meilleure façon de faire?

51
Florian

Lorsque les articles reçoivent leurs données configurées via the_post() (respectivement via setup_postdata()) et sont donc accessibles via l'API (get_the_ID() par exemple), supposons que nous parcourions un ensemble d'utilisateurs (sous la forme setup_userdata() remplit les variables globales de le actuellement connecté utilisateur et n'est pas utile pour cette tâche) et essayez d'afficher les métadonnées par utilisateur:

<?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' );
}

Ensuite, dans notre fichier wpse-theme/template-parts/user-contact_methods.php, nous devons accéder à l'ID utilisateur:

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

C'est tout.

L'explication est en réalité exactement au-dessus de la partie que vous avez citée dans votre question:

Cependant, load_template(), appelé indirectement par get_template_part(), extrait toutes les variables de requête WP_Query dans l'étendue du modèle chargé.

La PHPnative _ extract() function "extrait" les variables (la propriété global $wp_query->query_vars) et place chaque partie dans sa propre variable qui porte exactement le même nom que la clé. En d'autres termes:

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'
49
kaiser

La fonction hm_get_template_part de humanmade est extrêmement bonne et je l’utilise tout le temps.

Tu appelles

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

et à l'intérieur de votre modèle, vous utilisez

$template_args['option'];

pour renvoyer la valeur. Il met en cache et tout, même si vous pouvez le supprimer si vous le souhaitez.

Vous pouvez même renvoyer le modèle rendu sous forme de chaîne en passant 'return' => true dans le tableau clé/valeur.

/**
 * 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;
}
23
djb

Je cherchais autour de moi et ai trouvé une variété de réponses. Cela semble au niveau natif, Wordpress permet d’accéder aux variables dans les parties modèles. J'ai constaté que l'utilisation de l'include associée à la méthode position_template permettait aux variables de rester accessibles dans le fichier.

include(locate_template('your-template-name.php'));
11
Murray Chapman
// 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"

Je recommande de lire à propos de la fonction PHP Extract ().

3
Hugo R

J'ai rencontré le même problème sur un projet sur lequel je travaille actuellement. J'ai décidé de créer mon propre petit plugin qui vous permet de transmettre plus explicitement les variables à get_template_part en utilisant une nouvelle fonction.

Au cas où cela vous serait utile, voici la page correspondante sur GitHub: https://github.com/JolekPress/Get-Template-Part-With-Variables

Et voici un exemple de la façon dont cela fonctionnerait:

$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>
2
John O

J'aime les Pods plugin et leur pods_view function. Cela fonctionne de manière similaire à la fonction hm_get_template_part mentionnée dans la réponse de djb. J'utilise une fonction supplémentaire (findTemplate dans le code ci-dessous) pour rechercher un fichier de modèle dans le thème actuel, et si non trouvé, elle renvoie le modèle du même nom dans le dossier /templates de mon plugin. Ceci est une idée approximative de la façon dont j'utilise pods_view dans mon 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_view prend également en charge la mise en cache, mais je n'en avais pas besoin pour mes besoins. Vous trouverez plus d'informations sur les arguments de la fonction dans les pages de documentation de Pods. Reportez-vous aux pages relatives à pods_view et Mise en cache partielle et parties de modèle dynamique avec des nacelles .

1
thirdender

Basé sur la réponse de @djb en utilisant le code de humanmade.

Il s'agit d'une version allégée de get_template_part pouvant accepter les arguments. De cette façon, les variables sont localisées localement à ce modèle. Pas besoin d'avoir 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();
}

Par exemple, dans cart.php:

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

Dans Apple.php:

<p>The Apple color is: <?php echo $args['color']; ?></p>
1
Veedka

Que dis-tu de ça?

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();
    }
}

En utilisant ${$key}, vous pouvez ajouter les variables dans la portée de la fonction actuelle. Fonctionne pour moi, rapide et facile, sans fuite ni stockage global.

0
Mattijs