2009-12-29 10 views
15

Estaba escribiendo una aplicación web en PHP, cuando me encontré con una situación extraña. Para ilustrar mi problema, considere una aplicación web de esta estructura:¿Cómo funciona la resolución de ruta en require_once?

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

contenido de estos archivos:

index.php:

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

f1.php:

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

f2.php: en blanco

ahora, cuando intento abrir index.php en mi navegador me sale este error:

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 

¿Hay algo obvio que me falta? ¿Cómo funcionan las rutas incluidas en PHP?


Antes de hacer esta pregunta, intenté experimentar y descubrir. I fijó otra prueba, así:

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

index.php:

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

f1.php:

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

f2.php: blanco

Para mi sorpresa (y completa confusión), ¡todo salió bien!

Entonces, ¿cuál es el secreto detrás de la resolución de ruta?

PD Vi this question, pero todavía no responde el segundo caso que he mencionado aquí.

+0

Ya he eludido este problema (usando dirname). Lo que quiero saber es por qué el segundo caso no falla. ¿Es un error o una característica? – jrharshath

+0

Edité mi respuesta para cubrir el segundo ejemplo. – Karsten

+0

No puedo encontrar la página de manual que documenta la llamada exitosa a require_once ('f2.php') desde f1.php. Los documentos dicen que include_path se ignora cuando no se proporciona información de ruta (lo que sea, eliminar "." De include_path no tiene ningún efecto) y getcwd() muestra que el directorio de trabajo es el mismo en toda la cadena de inclusión. En serio, parece una característica no documentada. –

Respuesta

10

Si incluye otro archivo, el directorio de trabajo permanece donde se encuentra el archivo incluido.

Sus ejemplos funcionan según lo previsto.

Editar: El segundo ejemplo funciona porque. (directorio real) está en su ruta de inclusión (vea su mensaje de error).

Edit2: En el segundo ejemplo, el punto clave de su interés es esta línea:

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

Al principio se buscará en el directorio de trabajo actual (/var/www/req_path_test), pero no encuentra f2 .php.

Como alternativa, intentará encontrar f2.php en su include_path ('.:/usr/share/php:/usr/share/pear'), comenzando por '.' (que es relativo al archivo real, no el incluyendo uno).

Así que './f2.php' funciona y el requisito no falla.

+0

Probé echo: ing getcwd() en index.php y f1.php. La salida de ambos lugares es '/ var/www/req_path_test' por lo que". " estar en la ruta de inclusión probablemente significaría que "/ var/www/req_path_test" está en la ruta de inclusión. – jrharshath

+0

y en apoyo de este hecho, probé 'require_once (" f2/f2.php ")'. Funcionó cuando abrí index.php, pero no cuando abro f1/f1.php. – jrharshath

+0

Actualicé mi respuesta para cubrir su comentario. – Karsten

0

Normaly en ti antigua estructura

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

en lugar de

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

debería funcionar. Por lo que sé, php toma las rutas de la secuencia de comandos inicial

+0

Lo sé. Lo que realmente quiero saber es por qué el segundo caso no está fallando. No es un problema, es un picor :) – jrharshath

4

Al abrir index.php, el directorio de trabajo se establece en la carpeta en la que reside este archivo. Y dentro de f1.php inscrito este directorio de trabajo no cambia.

Puede incluir archivos mediante el uso de sus rutas absolutas, en relación con la corriente incluido el archivo de esta manera:

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

Pero es mejor considerar el uso de un cargador automático si estos archivos contienen clases.

+0

¿Qué pasa con el segundo caso? ¿Por qué está funcionando? – jrharshath

+0

Intenta agregar 'echo getcwd();' a sus scripts para ver cómo y si el directorio de trabajo actual cambia. http://php.net/manual/en/function.getcwd.php - los comentarios aquí dicen que su comportamiento cambió de PHP4 a PHP5, por ejemplo. –

0

Parece que su servidor tiene habilitada la configuración open_basedir en la configuración de PHP.Esto hace que sea imposible incluir (y abrir) archivos en carpetas encima de su en la estructura del directorio (es decir, no puede usar ../ para ir hacia arriba en la estructura de carpetas).

+0

en mi servidor, la configuración de open_basedir no tiene "ningún valor". ¿Qué significa eso? – jrharshath

+0

sin valor = deshabilitado – Karsten

+0

@Karsten lo que significa que "../" está permitido, ¿no? – jrharshath

Cuestiones relacionadas