2008-12-23 8 views
6

Voici un problème auquel j'ai récemment été confronté - un apache mal configuré sur un hébergeur. Cela signifie que tous les scripts qui s'appuient sur $_SERVER['DOCUMENT_ROOT'] break. La solution de contournement la plus simple que j'ai trouvée consiste simplement à définir la variable dans certains fichiers d'inclusion globaux partagés, mais il est difficile de ne pas l'oublier. Ma question est, comment puis-je déterminer la racine de document correcte par programme?Comment déterminer par programme la racine du document en PHP?

Par exemple, sur un hôte, la configuration est comme ceci:

$_SERVER['DOCUMENT_ROOT'] == '/htdocs' 

Les racines réelles du document sont:

test.example.com -> /data/htdocs/example.com/test 
www.example.com -> /data/htdocs/example.com/www 

Et je voudrais un script qui est exécuté à partir www.example.com/blog/ (sur le chemin /data/htdocs/example.com/www/blog) pour obtenir la valeur correcte de /data/htdocs/example.com/www.

Sur un autre hôte, la configuration est un peu différent:

$_SERVER['DOCUMENT_ROOT'] == '/srv' 
test.example.com -> /home/virtual_web/example.com/public_html/test 
www.example.com -> /home/virtual_web/example.com/public_html/www 

Y at-il une solution à cela? Ou est le seul moyen de ne jamais compter sur $_SERVER['DOCUMENT_ROOT'] et de réparer tous les logiciels que je cours sur mes sites? Corriger cela sur le côté de l'hébergement ne semble pas être une option, je n'ai pas encore rencontré un hôte où il a été configuré correctement. Le mieux que j'ai obtenu était une racine de document pointant vers www.example.com, qui était au moins à l'intérieur de open_basedir - ils utilisaient encore un autre schéma de nommage, www.example.com pointerait vers /u2/www/example_com/data/www/.

Répondre

2

Basé sur http://www.helicron.net/php/:

$localpath=getenv("SCRIPT_NAME"); 
$absolutepath=getenv("SCRIPT_FILENAME"); 
$_SERVER['DOCUMENT_ROOT']=substr($absolutepath,0,strpos($absolutepath,$localpath));  

J'ai dû changer l'astuce basename/realpath car elle renvoyait une chaîne vide sur mon hôte. Au lieu de cela, j'utilise SCRIPT_FILENAME. Cela ne fonctionnera probablement plus sur IIS (mais les scripts d'origine qui utilisaient la variable $ _SERVER ne le feraient probablement pas non plus).

0

PHP doit établirons le répertoire courant à celui du script est, donc tant que cela ne vous brisé devriez être en mesure de comprendre la racine du document à l'aide $_SERVER['SCRIPT_FILENAME'] et getcwd(). (Je ne me souviens pas de toutes les variables $ _SERVER du haut de ma tête, il peut y avoir quelque chose dans phpinfo() qui est plus utile.)

+0

Certains scripts que j'ai installés sont "trop ​​intelligents" et savent quel répertoire (par rapport à la racine de document théorique) ils sont installés, et l'ajoutent à la racine du document (après l'avoir récupéré de la base de données). Je devrais encore modifier le code pour chaque répertoire pour dépouiller les annuaires ... ou pas? –

7

En PHP5, il y a la constante magique __FILE__ qui contient le chemin absolu du fichier dans lequel il apparaît. Vous pouvez l'utiliser en combinaison avec dirname pour calculer la racine du document.

Vous pouvez mettre une déclaration comme la suivante dans un fichier de configuration

define ('DOCUMENT_ROOT', dirname(__FILE__)); 

cela devrait faire l'affaire

+1

L'astuce consistait à utiliser à la fois le nom absolu du fichier (provenant de la constante magique ou des variables du serveur) et à le combiner avec la connaissance du chemin absolu lié à la racine du document à partir de SCRIPT_NAME. –

+3

De PHP 5.3 c'est aussi '__DIR__' que ça remplace' dirname (__ FILE __) '. – Michael

+0

Mais cela retourne juste le dossier du fichier courant qui n'est pas nécessairement le dossier racine réel du serveur web. – Chuck

3

Il n'y a pas besoin de modifier tous les scripts.

Vous pouvez exécuter un fichier PHP avant l'exécution d'un script à l'aide de auto_prepend_file.

$_SERVER est juste un tableau, vous peut le modifier et définir $_SERVER['DOCUMENT_ROOT'] correcte. Pourquoi ne pas exiger que votre hébergeur configure ses serveurs correctement?

+0

Il est inutile d'exécuter ce script sur chaque exécution. – SchizoDuckie

+0

C'est inutile d'exécuter ce script sur * chaque * exécution. Mieux vaut le gérer avec un .htaccess au lieu de le régler. – SchizoDuckie

+0

Vous pouvez utiliser php_value dans .htaccess pour définir auto_prepend_file, mais l'auteur de la question a mentionné le serveur IIS qui, je suppose, ne le supporte pas. – Kornel

0

Ces types de choses ont tendance à s'attarder silencieusement dans votre code et ne sont jamais supprimés (mais restent actifs) jusqu'à ce que quelqu'un corrige le serveur. Alors tout va se briser à nouveau. Ou, déplacez vos affaires vers un hôte qui fonctionnera. Si c'est cassé, qui sait ce que vous trouverez ensuite.

+0

Je ne suis pas sûr s'il est possible de configurer l'hôte correctement, cela semble être un problème avec mod_vhost_alias (d'après un commentaire sur http://www.webmasterworld.com/apache/3640691.htm). –

2

C'est une des raisons pour lesquelles les gens siphonnent tout via un bootstrap /index.php en utilisant htaccess et/ou des chaînes de requête. Vous pouvez utiliser l'astuce dirname(__FILE__) indiquée ci-dessus et obtenir ainsi la base publique de votre application. Si vous êtes trop loin pour passer à un seul point d'entrée, une chose que j'ai vue est que les gens ont un en-tête commun à leur script qui parcourt l'arborescence pour trouver un fichier unique la base dir:

function findAppBase($dir) { 
    if(file_exists("$dir/unique_file.txt")) { 
     return $dir; 

    return findAppBase(dirname($dir)); 
} 

$base = findAppBase(dirname(__FILE__)); 

ce code n'a pas été testé, et il pourrait y avoir une façon plus lisse en utilisant les vars dans $_ENV ou $_SERVER qui fera ce que vous voulez ...

+0

Heureusement, ce n'est pas un problème, je n'ai qu'un seul point d'entrée. C'est juste que je cours le même logiciel sur plusieurs domaines et hôtes, et je dois le réparer pour chaque domaine. Je préférerais soumettre une solution en amont, donc je n'ai plus à m'en soucier. –

Questions connexes