2009-12-29 14 views
15

J'écrivais une application web en PHP, quand j'ai rencontré une situation étrange. Pour illustrer mon problème, envisager une application web de cette structure:Comment fonctionne la résolution de chemin dans require_once?

/ 
    index.php 
    f1/ 
     f1.php 
    f2/ 
     f2.php 

Contenu de ces fichiers:

index.php:

<?php require_once("f1/f1.php"); ?> 

f1.php:

<?php require_once("../f2/f2.php"); ?> 

f2.php: vide

maintenant, quand je tente d'ouvrir index.php dans mon navigateur je reçois cette erreur:

Warning: require_once(../f2/f2.php) [function.require-once]: 
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2 
Fatal error: require_once() [function.require]: 
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2 

Y at-il quelque chose d'évident, je suis absent? comment inclure les chemins fonctionnent en PHP?


Avant de poser cette question, j'ai tenté d'expérimenter et de découvrir. Je mis en place un autre test, comme ceci:

/ 
    index.php 
    f1/ 
     f1.php 
     f2.php 

index.php:

<?php require_once("f1/f1.php"); ?> 

f1.php:

<?php require_once("f2.php"); ?> 

f2.php: blank

À ma grande surprise (et confusion totale), cela a bien fonctionné!

Alors, quel est le secret derrière la résolution du chemin? PS J'ai vu this question, mais il ne répond toujours pas au deuxième cas que j'ai indiqué ici.

+0

J'ai déjà contourné ce problème (en utilisant dirname). Ce que je veux savoir, c'est pourquoi le second cas n'échoue pas. Est-ce un bug ou une fonctionnalité? – jrharshath

+0

Édité ma réponse pour couvrir le deuxième exemple. – Karsten

+0

Je ne trouve pas la page de manuel qui documente l'appel réussi à require_once ('f2.php') à partir de f1.php. Les docs disent que include_path est ignoré quand aucune information de chemin n'est fournie (quoi que ce soit, supprimer '.' De include_path n'a aucun effet) et getcwd() montre que le répertoire de travail est le même tout autour de la chaîne d'inclusion. Sérieusement, cela ressemble à une fonctionnalité non documentée. –

Répondre

10

Si vous incluez un autre fichier, le répertoire de travail reste là où se trouve le fichier inclus.

Vos exemples fonctionnent comme prévu.

Modifier: Le deuxième exemple fonctionne parce que. (répertoire réel) est dans votre chemin d'inclusion (voir votre message d'erreur).

Edit2: Dans votre deuxième exemple, le point clé de votre intérêt est cette ligne:

<?php require_once("f2.php"); ?> 

Au début, il regardera dans le répertoire de travail courant (/var/www/req_path_test), mais ne trouve pas f2 .php.

Comme repli, il essaiera de trouver f2.php dans votre include_path ('.:/usr/share/php:/usr/share/pear'), en commençant par '.' (qui est relatif au réel fichier, pas le , y compris un).

Donc, './f2.php' fonctionne et le require ne manque pas.

+0

J'ai essayé echo: ing getcwd() dans index.php et f1.php. La sortie des deux endroits est '/ var/www/req_path_test' donc". " être dans le chemin d'inclusion signifierait probablement "/ var/www/req_path_test" dans le chemin d'inclusion. – jrharshath

+0

et à l'appui de ce fait, j'ai essayé 'require_once (" f2/f2.php ")'. Cela a fonctionné quand j'ouvre index.php, mais pas quand j'ouvre f1/f1.php. – jrharshath

+0

J'ai mis à jour ma réponse pour couvrir votre commentaire. – Karsten

0

Normaly en vous ancienne structure

<?php require_once("f2/f2.php"); ?>

au lieu de

<?php require_once("../f2/f2.php"); ?>

devrait fonctionner. Pour autant que je sache, php emprunte les chemins du script initial

+0

Je sais. Ce que je veux vraiment savoir, c'est pourquoi le second cas ne manque pas. Ce n'est pas un problème, c'est une démangeaison :) – jrharshath

4

Lorsque vous ouvrez index.php, le répertoire de travail est défini sur le dossier dans lequel se trouve ce fichier. Et à l'intérieur de f1.php inséré, ce répertoire de travail ne change pas.

Vous pouvez inclure des fichiers en utilisant leurs chemins d'accès absolus, par rapport au fichier inclus en cours comme celui-ci:

require_once(dirname(__FILE__).'/../../test/file.php') 

Mais il vaut mieux envisager d'utiliser un chargeur automatique si ces dossiers contiennent des classes.

+0

Qu'en est-il du second cas? pourquoi ça marche? – jrharshath

+0

Essayez d'ajouter 'echo getcwd();' à vos scripts pour voir, comment et si le répertoire de travail actuel change. http://php.net/manual/fr/function.getcwd.php - les commentaires ici indiquent, que c'est le comportement changé de PHP4 à PHP5 par exemple. –

0

Il semble que votre serveur ait le paramètre open_basedir activé dans la configuration PHP.Cela rend impossible l'inclusion (et l'ouverture) de fichiers dans des dossiers situés au-dessus de la structure du répertoire (c'est-à-dire que vous ne pouvez pas utiliser ../ pour monter dans la structure de dossiers).

+0

sur mon serveur, le paramètre open_basedir n'a "aucune valeur". Qu'est-ce que cela veut dire? – jrharshath

+0

aucune valeur = désactivé – Karsten

+0

@Karsten qui signifie que "../" est autorisé, non? – jrharshath