Passare una variabile a get_template_part
Il WP Codex dice di fare così:
// Vuoi rendere disponibile $my_var al template part in `content-part.php`
set_query_var( 'my_var', $my_var );
get_template_part( 'content', 'part' );
Ma come faccio ad eseguire echo $my_var
all'interno del template part? get_query_var($my_var)
non funziona nel mio caso.
Ho visto molte raccomandazioni sull'utilizzo di locate_template
al suo posto. È questo il modo migliore di procedere?

Poiché i post ottengono i loro dati impostati tramite the_post()
(rispettivamente tramite setup_postdata()
) e sono quindi accessibili attraverso l'API (get_the_ID()
ad esempio), supponiamo che stiamo ciclando attraverso un insieme di utenti (poiché setup_userdata()
riempie le variabili globali dell'utente attualmente loggato e non è utile per questo compito) e proviamo a visualizzare i metadati per utente:
<?php
get_header();
// etc.
// Nel file template principale
$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' );
}
Poi, nel nostro file wpse-theme/template-parts/user-contact_methods.php
, dobbiamo accedere all'ID dell'utente:
<?php
/** @var int $user_id */
$some_meta = get_the_author_meta( 'some_meta', $user_id );
var_dump( $some_meta );
Ecco fatto.
Aggiornamento (WP >= v5.5)
Come sottolineato nei commenti, le versioni recenti di WP offrono un terzo parametro per get_template_part()
: array $args
. Quindi da questa versione in poi non è più necessario usare set_query_var( 'foo', 'bar' )
. Esempio:
<?php
get_header();
// etc.
// Nel file template principale
$users = new \WP_User_Query( [ ... ] );
foreach ( $users as $user )
{
$args = (array) $user;
get_template_part( 'template-parts/user', 'contact_methods', $args );
}
Poi, nel nostro file wpse-theme/template-parts/user-contact_methods.php
, dobbiamo accedere all'ID dell'utente:
<?php
/** @var array $args */
$some_meta = get_the_author_meta( 'some_meta', $args['ID'] );
var_dump( $some_meta );
La spiegazione è in realtà esattamente sopra la parte che hai citato nella tua domanda:
Tuttavia,
load_template()
, che viene chiamato indirettamente daget_template_part()
, estrae tutte le variabili di query diWP_Query
, nell'ambito del template caricato.
La funzione nativa di PHP extract()
"estrae" le variabili (la proprietà global $wp_query->query_vars
) e mette ogni parte nella sua variabile che ha esattamente lo stesso nome della chiave. In altre parole:
set_query_var( 'foo', 'bar' );
$GLOBALS['wp_query'] (object)
-> query_vars (array)
foo => bar (string 3)
extract( $wp_query->query_vars );
var_dump( $foo );
// Risultato:
(string 3) 'bar'

La funzione hm_get_template_part
di humanmade è estremamente efficace per questo scopo e la uso continuamente.
La chiami con
hm_get_template_part( 'percorso_template', [ 'opzione' => 'valore' ] );
e poi all'interno del tuo template, usi
$template_args['opzione'];
per ottenere il valore. Gestisce anche la cache e tutto il resto, anche se puoi rimuoverlo se preferisci.
Puoi persino ottenere il template renderizzato come stringa passando 'return' => true
nell'array di chiavi/valori.
/**
* Simile a get_template_part() ma permette di passare argomenti al file template
* Gli argomenti sono disponibili nel template come array $template_args
* @param string filepart
* @param mixed wp_args lista di argomenti in stile WP
*/
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;
}

Stavo cercando in giro e ho trovato diverse risposte. Sembra che a livello nativo, WordPress non permetta di accedere alle variabili nelle parti dei template. Ho però scoperto che utilizzando l'include insieme a locate_template è possibile rendere accessibile l'ambito delle variabili nel file.
include(locate_template('your-template-name.php'));

L'uso di include
non supererà il controllo di themecheck.

// puoi utilizzare qualsiasi valore compresi gli oggetti.
set_query_var( 'var_name_to_be_used_later', 'Valore da recuperare successivamente' );
// Fondamentalmente set_query_var utilizza la funzione PHP extract() per fare la magia.
poi più avanti nel template.
var_dump($var_name_to_be_used_later);
// stamperà "Valore da recuperare successivamente"
Consiglio di leggere riguardo alla funzione PHP Extract().

Aggiornamento
Come selrond ha correttamente risposto, a partire da WordPress 5.5 la funzione get_template_part() (vedi changelog) accetta ora un terzo parametro array $args = array()
, che sarà disponibile nel tuo file template come $args
.
Vedi questo esempio:
$bar = 'bar';
// ottieni helper-my-template.php
get_template_part(
'template-parts/helper',
'my-template',
array(
'foo' => $bar, // passare questo array è possibile da WP 5.5
)
);
Nel tuo file template
Ad esempio in helper-my-template.php puoi ora accedere alla tua variabile così:
<?php
/**
* @var array $args
*/
$foo = $args['foo'];
?>
<h1><?php echo $foo; ?></h1>
<?php // stamperà 'bar' ?>

A partire dalla versione 5.5, sarà possibile passare dati ai template attraverso le varie funzioni core di caricamento dei template.
Tutte le funzioni di WordPress per il caricamento dei template supporteranno un parametro aggiuntivo $args
, che permette agli autori di temi di passare un array associativo di dati al template caricato. Le funzioni che supportano questo nuovo parametro sono:
get_header()
get_footer()
get_sidebar()
get_template_part()
locate_template()
load_template()
Anche gli hook associati a queste funzioni riceveranno i dati passati.
Per maggiori informazioni: https://make.wordpress.org/core/2020/07/17/passing-arguments-to-template-files-in-wordpress-5-5/

Mi sono imbattuto nello stesso problema in un progetto su cui sto attualmente lavorando. Ho deciso di creare un mio piccolo plugin che permette di passare in modo più esplicito le variabili a get_template_part utilizzando una nuova funzione.
Nel caso possa esserti utile, ecco la pagina su GitHub: https://github.com/JolekPress/Get-Template-Part-With-Variables
Ed ecco un esempio di come funzionerebbe:
$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>
";
// Output generato:
<div class='featuredAuthor'>
<span>John</span>
</div>

Il parametro $args
per le funzioni di caricamento dei template è stato introdotto in WordPress 5.5 "Eckstine":
Passaggio di dati ai file template
Le funzioni di caricamento dei template (get_header(), get_template_part(), ecc.) ora hanno un nuovo argomento $args. Questo permette di passare un intero array di dati a questi template.

Mi piace il plugin Pods e la sua funzione pods_view. Funziona in modo simile alla funzione hm_get_template_part
menzionata nella risposta di djb. Utilizzo una funzione aggiuntiva (findTemplate
nel codice qui sotto) per cercare prima un file template nel tema corrente e, se non trovato, restituisce il template con lo stesso nome nella cartella /templates
del mio plugin. Ecco un'idea approssimativa di come utilizzo pods_view
nel mio plugin:
/**
* Funzione helper per trovare un template
*/
function findTemplate($filename) {
// Cerca prima nella cartella del tema
$template = locate_template($filename);
if (!$template) {
// Altrimenti, utilizza il file nella cartella /templates del plugin
$template = dirname(__FILE__) . '/templates/' . $filename;
}
return $template;
}
// Mostra il template 'template-name.php' dalla cartella del tema
// *oppure* dalla cartella '/template' del plugin, passando due variabili
// locali che saranno disponibili nel file template
pods_view(
findTemplate('template-name.php'),
array(
'passed_variable' => $variable_to_pass,
'another_variable' => $another_variable,
)
);
pods_view
supporta anche la cache, ma non ne avevo bisogno per i miei scopi. Maggiori informazioni sugli argomenti della funzione possono essere trovate nella documentazione di Pods. Consulta le pagine per pods_view e Cache Parziale di Pagina e Template Part Intelligenti con Pods.

Basato sulla risposta di @djb utilizzando il codice di humanmade.
Questa è una versione leggera di get_template_part che può accettare argomenti. In questo modo le variabili sono limitate localmente a quel template. Non è necessario utilizzare global
, get_query_var
, set_query_var
.
/**
* Come get_template_part() ma permette di passare argomenti al file template
* Gli argomenti sono disponibili nel template come array $args.
* Gli argomenti possono essere passati come parametri URL, es. 'key1=value1&key2=value2'.
* Gli argomenti possono essere passati come array, es. ['key1' => 'value1', 'key2' => 'value2']
* Il percorso del file è disponibile nel template come stringa $file.
* @param string $slug Lo slug per il template generico.
* @param string|null $name Il nome del template specializzato.
* @param array $args Gli argomenti passati al 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();
}
Ad esempio in cart.php
:
<?php _get_template_part( 'components/items/apple', null, ['color' => 'red']); ?>
In apple.php
:
<p>Il colore della mela è: <?php echo $args['color']; ?></p>

Che ne pensi di questo?
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();
}
}
Utilizzando ${$key}
puoi aggiungere le variabili nell'ambito della funzione corrente.
Funziona per me, è veloce e semplice e non fa trapelare né memorizza nell'ambito globale.

Per chi cerca un modo molto semplice per passare le variabili, puoi modificare la funzione per includere:
include( locate_template( 'YourTemplate.php', false, false ) );
E così sarai in grado di utilizzare tutte le variabili definite prima di includere il template senza doverle PASSARE ulteriormente una per una al template.
Crediti a: https://mekshq.com/passing-variables-via-get_template_part-wordpress/

Questa è la soluzione esatta e ha funzionato perfettamente. https://developer.wordpress.org/reference/functions/set_query_var/
