Includere un file PHP nel contenuto usando [shortcode]
Ecco cosa ho a disposizione
Non riesco a trovare un modo per includere semplicemente un file nell'editor dei contenuti usando uno shortcode.
Per esempio, se volessi includere form.php all'interno della mia Pagina Contatti, come potrei farlo usando uno shortcode?
Qui sotto c'è quello che stavo cercando di far funzionare senza successo.
Ogni aiuto sarebbe apprezzato!
// Implementazione Shortcode
function magic_stuff($atts) {
// attiva il buffering dell'output per catturare l'output dello script
ob_start();
// includi il file (il contenuto verrà salvato nel buffer di output)
include(TEMPLATEPATH.'/wp-content/themes/grainandmortar/inc_static/test.php');
// salva e restituisci il contenuto che è stato generato
$content = ob_get_clean();
return $content;
}
//registra il gestore dello Shortcode
add_shortcode('magic', 'magic_stuff');
Ecco un altro modo per farlo, utilizzando get_template_part
di WordPress
function include_file($atts) {
$a = shortcode_atts( array(
'slug' => 'NULL',
), $atts );
if($a['slug'] != 'NULL'){
ob_start();
get_template_part($a['slug']);
return ob_get_clean();
}
}
add_shortcode('include', 'include_file');
esempi:
[include slug="form"]
[include slug="sub-folder/filename_without_extension"]

Ho modificato del codice da un vecchio post del blog per fare questo, e permettere anche di allegare query-string al file.
Il merito originale va a amberpanther.com, e a quanto pare hanno anche creato un plug-in con questa funzionalità.
//crea lo shortcode [include] che accetta un percorso file e una query string
//questa funzione è stata modificata da un post su www.amberpanther.com che puoi trovare al link sotto:
//http://www.amberpanther.com/knowledge-base/using-the-wordpress-shortcode-api-to-include-an-external-file-in-the-post-content/
//INIZIO codice amberpanther.com
function include_file($atts) {
//se è specificato un percorso file
extract(
shortcode_atts(
array(
'filepath' => 'NULL'
), $atts
)
);
//INIZIO porzione di codice modificata per accettare query string
//controlla presenza di query string dopo il percorso file
if(strpos($filepath,"?")) {
$query_string_pos = strpos($filepath,"?");
//crea variabile globale per la query string per accedervi nei file inclusi
//e separala dal percorso file pulito che memorizzeremo in una nuova variabile
global $query_string;
$query_string = substr($filepath,$query_string_pos + 1);
$clean_file_path = substr($filepath,0,$query_string_pos);
//se non c'è query string
} else {
$clean_file_path = $filepath;
}
//FINE porzione modificata
//controlla se il percorso è specificato e se il file esiste
if ($filepath != 'NULL' && file_exists(get_stylesheet_directory_uri() . "/" . $clean_file_path)){
//attiva output buffering per catturare l'output
ob_start();
//includi il file specificato
include(TEMPLATEPATH.$clean_file_path);
//assegna l'output a $content e pulisci il buffer
$content = ob_get_clean();
//restituisci $content
//il return è importante per far apparire l'output nella posizione corretta
//nel contenuto
return $content;
}
}
//registra l'handler dello shortcode
add_shortcode('include', 'include_file');
//FINE codice amberpanther.com
//esempio di shortcode con query string:
//[include filepath="/get-posts.php?format=grid&taxonomy=testing&term=stuff&posttype=work"]
Ho impostato il mio codice per prelevare dall'URI del tema figlio (così funziona con i child theme e simili), ma potresti facilmente modificare quel codice per prelevare da qualsiasi posizione (incluso le directory dei plugin), o rimuoverlo del tutto e usare semplicemente il percorso completo quando includi il file. Potresti anche aggiungere una condizione con un carattere trigger all'inizio che indica di usare un percorso specifico basato sul primo carattere del nome file, come usare "#" per la directory del template, ecc.
Lo uso per includere un file chiamato get-posts.php che si trova nella mia directory del template e formatta l'output di vari post basandosi su una serie di parametri forniti nella query string. Mi evita di dover creare template speciali perché posso includere il file, inviargli un formato e restituirà i post con il markup che ho specificato nel file get-posts.php.
Permette anche ai clienti di includere custom post type all'interno di post del blog veri e propri in formati specifici ed è molto utile.
Fammi sapere se hai bisogno di chiarimenti su qualcosa.

Non dovresti usare TEMPLATEPATH
o STYLESHEETPATH
. Usa invece get_template/stylesheet_dir()
o l'equivalente *_url()
per i percorsi/URI

ericissocial Grazie mille! Ora inserirò tutto e proverò, ti farò sapere come va.

Nessun problema, dovresti seguire il consiglio di kaiser e usare la funzionalità GET_template invece del TEMPLATEPATH che avevo nel codice. Kaiser, grazie per il suggerimento, modificherò il codice nella mia risposta quando non lo sto visualizzando dal telefono.

C'è un errore nella soluzione fornita da @adedoy, poiché $slug non è mai definito. Questo ha funzionato per me:
function include_file($atts) {
$atts = shortcode_atts(
array(
'path' => 'NULL',
), $atts, 'include' );
ob_start();
get_template_part($atts['path']);
return ob_get_clean();
}
add_shortcode('include', 'include_file');
Utilizzo: [include path="percorso/dalla/root"]

Ok, per prima cosa eliminerei l'output buffering.
Seconda modifica:
include(TEMPLATEPATH.'/wp-content/themes/grainandmortar/inc_static/test.php');
Diventa
include( get_stylesheet_directory() . '/inc_static/test.php');
Infine,
Leggendo la documentazione qui: https://codex.wordpress.org/Shortcode_API
Devi restituire qualcosa, se il tuo test.php non restituisce qualcosa in modo adeguato, avrai problemi.
Quindi assicurati che test.php faccia qualcosa del genere:
$output = "CONTENUTO"; // una variabile che puoi restituire dopo l'inclusione.
// oppure
function test() {
// fai qualcosa
return $valore; // una funzione che restituisce un valore che puoi chiamare dopo l'inclusione.
}
Poi dopo aver incluso il tuo file test.php - dovrai semplicemente restituire $output
o fare qualcosa come return test();
.

Solo curioso di capire il tuo ragionamento - perché non usare l'output buffering per gli shortcode?

Ciao @mattLummus -- alla fine è una questione di prospettiva. Penso che non ti serva per raggiungere l'obiettivo e non guadagni molto usandolo -- inoltre, ribadisco quanto detto qui: https://stackoverflow.com/questions/5454345/output-buffer-vulnerabilities-php -- "L'output buffering è considerato brutto se usato per aggirare il classico avviso Cannot send headers, output already started at... L'output buffering viene quindi utilizzato per compensare un design scadente..."

Sì, in quel caso specifico sembra davvero una soluzione un po' approssimativa. In genere quando usiamo gli Output Buffer non è per aggirare un altro problema, ma semplicemente perché ci troviamo in una situazione in cui scriviamo più markup che PHP e preferiamo la sintassi OB (poter uscire da PHP e scrivere HTML normale rispetto a un mucchio di istruzioni echo e HTML scritto in stringhe).
Grazie comunque per la risposta!

Ho riscontrato che il codice include originariamente scritto dal team di AmberPanther non funzionava bene per me, quindi ho trovato un altro plugin WordPress che fa praticamente la stessa cosa. Si chiama Include Me, sviluppato da Stefano Lissa. L'utilizzo è abbastanza semplice: devi scrivere il percorso del file a partire dalla directory root del tuo sito.
Ad esempio, all'interno della tua pagina WordPress scriveresti:
[includeme file="wp-content/themes/your-theme/code/example-code.php"]
e all'interno del tuo file functions.php includeresti:
<?php
if (is_admin()) {
include dirname(__FILE__) . '/admin.php';
} else {
function includeme_call($attrs, $content = null) {
if (isset($attrs['file'])) {
$file = strip_tags($attrs['file']);
if ($file[0] != '/')
$file = ABSPATH . $file;
ob_start();
include($file);
$buffer = ob_get_clean();
$options = get_option('includeme', array());
if (isset($options['shortcode'])) {
$buffer = do_shortcode($buffer);
}
} else {
$tmp = '';
foreach ($attrs as $key => $value) {
if ($key == 'src') {
$value = strip_tags($value);
}
$value = str_replace('&', '&', $value);
if ($key == 'src') {
$value = strip_tags($value);
}
$tmp .= ' ' . $key . '="' . $value . '"';
}
$buffer = '<iframe' . $tmp . '></iframe>';
}
return $buffer;
}
// Qui perché la funzione DEVE essere definita prima di "add_shortcode" poiché
// "add_shortcode" verifica il nome della funzione con "is_callable".
add_shortcode('includeme', 'includeme_call');
}
Naturalmente, consiglio anche di installare semplicemente il plugin per poter sfruttare gli aggiornamenti. https://wordpress.org/plugins/include-me/
