2010-07-11 16 views
39

In localhost. Ho la seguente struttura di directory:In che modo PHP, Symlink e __FILE__ funzionano bene insieme?

/share/www/trunk/wp-content/plugins/otherfolders

/share/www/portfolio/wp-content/symlink

Dove symlink è un link simbolico a /trunk/.../plugins/. Fondamentalmente, questo è perché ho bisogno di testare più installazioni di WordPress e impostarle, ma non voglio dover spostare i plugin in giro e copiarli e incollarli ovunque.

Tuttavia, a volte ho bisogno di strisciare l'albero di directory per includere un file di configurazione:

$root = dirname(dirname(dirname(dirname(__FILE__)))); 
     if (file_exists($root.'/wp-load.php')) { 
      // WP 2.6 
      require_once($root.'/wp-load.php'); 
     } 

La cartella si risolve sempre:

/share/www/trunk

Anche quando è in esecuzione il plugin e incluso in

/share/www/portfolio/.

E 'possibile in PHP includere file nella directory da uno script eseguito in un collegamento simbolico alla directory /share/www/trunk/.../plugins?

Mentre questo problema si verifica solo sul mio server di test, mi piacerebbe avere una soluzione distribuibile in modo che la scansione di un livello extra non sia un'opzione.

+0

Sai dove lo script in cui si sta facendo l'azienda __FILE__ è relativo al punto di ingresso? Che cosa equivale a $ _SERVER ['SCRIPT_FILENAME'] nel contesto del tuo esempio? – Shabbyrobe

+0

Bingo. So esattamente quante directory ho bisogno di gattonare. Ho solo bisogno di avere la giusta directory di base. Pubblica la risposta e la taglia è tua. –

+0

Un'altra idea sarebbe utilizzare i collegamenti fisici anziché i collegamenti simbolici. O c'è un motivo per cui hai bisogno di collegamenti simbolici (come altri punti di mount, ecc.)? – JochenJung

risposta

28

Il problema che vedo con il codice è che __FILE__ risolve automaticamente i collegamenti simbolici.

dal manuale PHP su Magic Constants

... Dal PHP 4.0.2, __FILE__ contiene sempre un percorso assoluto con link simbolici risolti ...

Puoi provare a utilizzare $_SERVER["SCRIPT_FILENAME"] invece.

$root = realpath(dirname(dirname(dirname(dirname($_SERVER["SCRIPT_FILENAME"]))))); 
    if (file_exists($root.'/wp-load.php')) { 
     // WP 2.6 
     require_once($root.'/wp-load.php'); 
    } 

Nota che ho aggiunto la funzione realpath() alla directory principale. A seconda della configurazione, potrebbe essere necessario o meno.

MODIFICA: utilizzare $_SERVER["SCRIPT_FILENAME"] anziché $_SERVER["PHP_SELF"] per il percorso del file system.

+0

PHP_SELF fornisce solo il valore del file di elaborazione corrente. Il risultato finale deve essere un percorso assoluto non un URI. –

+0

Il mio male ... Inizialmente stavo provando dalla CLI. Che ne dici di usare $ _SERVER ["SCRIPT_FILENAME"]? Questo ha funzionato nel mio ambiente. Se ciò non funziona, cosa significa Preventare $ _SERVER ["DOCUMENT_ROOT"] a $ _SERVER ["PHP_SELF"]? – pferate

+0

Quello che segue è il bug del tuo problema: https://bugs.php.net/bug.php?id = 46260 Purtroppo, PHP non cambierà in questo modo, che è un bug secondo me. –

0

Se stessi cercando di risolvere questo problema, mi piacerebbe dividere __FILE__ lungo i bit di percorso e creare una SplFileInfo per ciascuna lungo la strada, prova con isDir e isLink, quindi provare a stabilire come gestire la ricostruzione del percorso di una volta che è noto per essere diverso dal previsto in modo da poter estrarre dalla directory giusta. (Se sei più di un tipo procedurale, c'è is_dir e is_link.)

Detto questo, penso che tu abbia già squalificato questa soluzione. Forse gli strumenti sono abbastanza intelligenti da farlo per te. Prova a confrontare il risultato di getRealPath a getPath? getRealPath dice espressamente che risolve i collegamenti simbolici, mentre getPath non lo dice espressamente.

Anche in questo caso, questo sniffing potrebbe non essere sicuro sui siti dei client, a seconda di chi è l'host. Ho visto alcune soluzioni creative per il file system di hosting condiviso creative. È possibile aggiungere un assegno a php_uname ed estrarre il nome host della macchina, e se non è la propria casella di sviluppo, non eseguire il lavoro aggiuntivo.

+1

Sfortunatamente, 'getRealPath' e' getPath' generano tutti la directory '/ trunk /'. –

1

L'interprete PHP risolve i collegamenti simbolici prima che vengano elaborati. Puoi farlo tu stesso con la funzione readlink. PHP risolve i collegamenti perché è più efficiente per le funzioni *_once e cache di codice come APC, Xcache ecc.

Ciò di cui si ha bisogno è un altro modo per trovare dove una particolare installazione memorizza i propri file. Ti consigliamo di utilizzare {$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php assumendo che /share/www/portfolio sia la radice del documento.

+0

La radice del documento è sfortunatamente/share/www/ –

2

È possibile utilizzare questo snippet di codice per ottenere un percorso in cui i collegamenti simbolici non vengono risolti. Se non hai bash disponibile, probabilmente c'è un comando diverso che puoi usare, ma funziona su ambienti linux.

Penso che sia una cattiva pratica che php risolva i collegamenti simbolici in FILE, poiché non c'è modo di ottenere il percorso con i collegamenti simbolici. Altrimenti potremmo facilmente ottenerlo usando realpath.

Oh bene.

<?php 
$output = array(); 
exec('pwd', &$output); 
define('__LINK__', $output[0].substr(__FILE__, strpos(__FILE__, DIRECTORY_SEPARATOR))); 
?> 
+1

Il valore restituito 'pwd' dipende dalla directory di lavoro corrente; Per funzionare in modo appropriato, è necessario prima modificare la directory di lavoro: cd/var/www/wp-content/themes/twenty_twelve/&& php script.php – AndreyP

+0

Ho rimosso il '&', e '$ output [0]' ha funzionato per me . –

2

In qualche caso la sua possibile cambiare dir di lavoro e utilizzare getenv ('PWD'):

$root = dirname(dirname(dirname(getenv('PWD')))); 
if (file_exists($root.'/wp-load.php')) { 
    // WP 2.6 
    require_once($root.'/wp-load.php'); 
} 

e cambiare la directory di lavoro prima di eseguire questo codice:

cd /var/www/wp-content/themes/twenty_twelve/ && php script.php 
1

Ecco la soluzione a questo problema: https://github.com/logical-and/symlink-detective

$root = dirname(dirname(dirname(dirname(__FILE__)))); 
    if (file_exists(SymlinkDetective::detectPath($root.'/wp-load.php'))) { 
     // WP 2.6 
     require_once(SymlinkDetective::detectPath($root.'/wp-load.php')); 
    } 

oppure si può provare che

try { 
    $root = dirname(dirname(dirname(dirname(__FILE__)))); 
    require_once SymlinkDetective::detectPath($root.'/wp-load.php', '', 
    false /* this would throw an exception if file doesn't exists */); 
} 
catch (Exception $e) { 
    // nothing to do if file doesn't exists 
} 
+1

Non capisco davvero perché tu abbia rimosso la mia risposta. Ho scritto una soluzione per il problema, ho dato esempi su come può essere utilizzato, ho scritto quella risposta. Prova a fare lo stesso, invece di rimuovere il mio post o fammi sapere almeno perché? Le mie informazioni non sono utili? – And

Problemi correlati