Come includere wp-load.php da qualsiasi posizione?
Ho un plugin che richiama uno script PHP standalone (myAjax.php) tramite uno script jQuery.ajax() all'interno del plugin.
Ho bisogno di inserire il seguente codice nel file myAjax.php:
require_once('../../../wp-load.php');
if (!is_user_logged_in()){
die("Devi essere loggato per accedere a questa risorsa");
}
if( ! current_user_can('edit_files')) {
die("Spiacente, non sei autorizzato ad accedere a questo file");
}
Tuttavia, vorrei un metodo più sicuro per specificare il percorso a wp-load.php nel caso in cui il percorso relativo effettivo sia diverso dal mio esempio.
Puoi utilizzare la costante __DIR__. Dato che il file si trova all'interno della cartella di un plugin o di un tema, che sono sempre situati dentro la cartella wp-content.. Puoi semplicemente ottenere il percorso del file e tagliare tutto a partire da wp-content:
$path = preg_replace( '/wp-content.*$/', '', __DIR__ );
Se hai bisogno di assicurarti che wp non sia dentro qualche cartella wp-content (chi lo sa? può capitare) - usa il negative lookahead:
$path = preg_replace( '/wp-content(?!.*wp-content).*/', '', __DIR__ );
(dato che è più facile essere certi che il tuo plugin in sviluppo non si trovi dentro qualche altra cartella wp-content)
Eee.. il tuo wp-load è qui:
require_once( $path . 'wp-load.php' );
Migliore Pratica
Come menzionato prima, per AJAX dovresti usare la tecnica admin-ajax di WordPress o la nuova REST API.
So che questa è una domanda vecchia, ma volevo aggiungere la mia risposta che penso possa aiutare alcuni utenti che cercano di ottenere lo stesso risultato.
Sì, è sempre meglio (e più facile) usare l'API AJAX nativa di WordPress, ma può diventare molto lenta perché carica l'intera istanza di WP.
La mia soluzione: è abbastanza semplice e dovrebbe funzionare per recuperare la root dell'installazione di WordPress. In qualsiasi script stai facendo la chiamata AJAX personalizzata, assicurati prima di registrare lo script con wp_register_script() (non ancora di inserirlo in coda). Poi usa wp_localize_script() e passa la costante ABSPATH (questa è una costante definita all'interno di wp-load.php e conterrà il percorso root). Ora puoi recuperare questo valore all'interno del tuo script e passarlo insieme alla chiamata AJAX. Infine, ovviamente, assicurati di inserire effettivamente lo script in coda con wp_enqueue_script().
Esempio:
Il seguente snippet PHP inserirà in coda il tuo file script.js e ti permetterà di recuperare la directory root chiamando pluginslug_scriptname_i18n.wp_root. Fondamentalmente wp_localize_script() viene usato per le traduzioni, ma torna utile anche per passare dati al tuo script che hai recuperato lato server.
$handle = 'pluginslug-scriptname'; // Imposta l'handle dello script
$name = str_replace( '-', '_', $handle ) . '_i18n'; // Convertirà l'handle in pluginslug_scriptname_i18n
wp_register_script( $handle, plugin_dir_url( __FILE__ ) . 'script.js', array(), '1.0.0', false );
wp_localize_script(
$handle,
$name,
array(
'ajax_url' => plugin_dir_url( __FILE__ ) . 'ajax-handler.php', // @QUESTO CONTERRÀ IL TUO URL AJAX :) Per recuperarlo all'interno di script.js chiama semplicemente: pluginslug_scriptname_i18n.ajax_url
'wp_root' => ABSPATH // @QUESTO CONTERRÀ IL PERCORSO ROOT :) Per recuperarlo all'interno di script.js chiama semplicemente: pluginslug_scriptname_i18n.wp_root
)
);
wp_enqueue_script( $handle );
Il tuo script.js potrebbe essere così:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 ){
if (this.status == 200) {
// Successo:
}
// Completato:
}
};
xhttp.onerror = function () {
console.log(this);
console.log("** Si è verificato un errore durante la transazione");
};
xhttp.open("POST", pluginslug_scriptname_i18n.ajax_url, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
var params = JSON.stringify({
first_name: 'Johny',
wp_root: pluginslug_scriptname_i18n.wp_root
});
xhttp.send(params);
Ora all'interno del tuo ajax-handler.php puoi recuperare la wp_content_dir e caricare il tuo wp-load.php così:
// Imposta il corretto content type
header('Content-Type: text/html');
// Disabilita la cache
header('Cache-Control: no-cache');
header('Pragma: no-cache');
// Ottiene il payload
$request_body = json_decode( file_get_contents('php://input'), true );
// Imposta questo a true per caricare solo l'essenziale!
// Impostalo a true solo se sai cosa stai facendo
// Cerca SHORTINIT in wp-settings.php per maggiori dettagli
define( 'SHORTINIT', false );
// Includi wp-load.php
require_once( $request_body['wp_root'] . 'wp-load.php' );
die();
Ricorda che il valore di wp_root può essere modificato lato client.
Come nota a margine:
Un altro trucco di cui alcuni potrebbero non essere a conoscenza è che prima di includere wp-load.php puoi definire una costante chiamata SHORTINIT (booleana). Questo dirà a WordPress di caricare solo l'essenziale (significa che perderai molte funzioni core di WP) ma velocizzerà il tempo di caricamento poiché non includerà tutti i file necessari per una normale istanza di WP. La costante SHORTINIT è definita all'interno di wp-settings.php (apri il file e cerca SHORTINIT. Avrai una migliore comprensione di cosa succede sotto il cofano. Questo trucco velocizzerà ulteriormente i tempi di caricamento (fino al 75% nei test che ho fatto tempo fa). Ma questo dipenderà dalla versione di WP. Tieni anche presente che wp-load.php cambia frequentemente con le nuove versioni di WP, quindi se usi SHORTINIT assicurati che il tuo script funzioni sempre anche nelle future versioni di WordPress e anche con versioni più vecchie. In breve, se fai cose complesse che si affidano a gran parte del codex di WordPress, allora assicurati di NON impostare SHORTINIT a true.
Suggerisco questo come un possibile metodo "infallibile" per trovare il percorso a wp-load.php purché si trovi in una directory superiore rispetto a dove stai eseguendo lo script.
echo get_wp_abspath('wp-load.php') . PHP_EOL;
function get_wp_abspath($filename)
{
$_DIR = __DIR__; // posizione di questo script
$_FILE = $_DIR . '/' . $filename; // percorso completo/file
while(!file_exists($_FILE)) // se non trovato
{
$_DIR = dirname($_DIR); // sali di un livello (es. ../)
$_FILE = $_DIR . '/' . $filename; // nuovo percorso completo/file
if($_DIR == '/') return FALSE; // se raggiungiamo il percorso base, fallisci
}
return $_FILE; // se il file è trovato, restituisci percorso completo/file
}