¿Cómo funciona la resolución de ruta de acceso en require_once?

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:

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

Contenido de estos archivos:

index.php:

  

f1.php:

  

f2.php: en blanco

Ahora, cuando bash abrir index.php en mi navegador, aparece 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 de inclusión en PHP?


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

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

index.php:

  

f1.php:

  

f2.php: en blanco

Para mi sorpresa (y confusión total), esto funcionó bien!

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

PD: vi esta pregunta , pero aún no responde al segundo caso que he expuesto aquí.

Si incluye otro archivo, el directorio de trabajo permanece donde está el archivo incluido.

Sus ejemplos están funcionando según lo previsto.

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

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

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

Al principio se verá 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 con ‘.’ (que es relativo al archivo real , no el que incluye ).

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

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

Puede incluir archivos utilizando sus rutas absolutas, en relación con el archivo incluido actual como este:

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

Pero mejor considere usar un autocargador si estos archivos contienen clases.

Normaly en tu vieja estructura.

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

en lugar de

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

Deberia trabajar. Por lo que sé, PHP toma las rutas del script inicial.

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 por encima de usted en la estructura del directorio (es decir, no puede usar ../ para subir en la estructura de carpetas).

Desde PHP Docs PHP incluye

Los archivos se incluyen según la ruta de acceso del archivo o, si no se proporciona, la ruta de inclusión especificada. Si el archivo no se encuentra en include_path, include finalmente registrará el propio directorio del script de llamada y el directorio de trabajo actual antes de fallar.

Si no se proporciona la ruta del archivo, es decir, require_once (“f2.php”);

Primero El include_path está marcado

2do. El propio directorio de scripts de llamada está marcado.

3er. Finalmente se comprueba el directorio de trabajo actual.

Si no se encuentra el archivo, PHP lanza una advertencia en el archivo que incluye y un error fatal si se requiere

Si se define una ruta, ya sea absoluta (comenzando con una letra de unidad o \ en Windows, o / en sistemas Unix / Linux) o en relación con el directorio actual (comenzando con. O …), la include_path se ignorará por completo. Por ejemplo, si un nombre de archivo comienza con ../, el analizador buscará en el directorio principal para encontrar el archivo solicitado.

Si incluye / requiere su archivo a partir de. o … o ./ luego el analizador de PHP buscará en el directorio principal, que es el directorio de trabajo actual, es decir, require_once (“../ f2 / f2.php”), php comprobará en el directorio raíz como el script index.php esta en ese directorio

Ahora no ha definido ninguna ruta de inclusión en su secuencia de comandos PHP, por lo que siempre recurre a la secuencia de comandos de llamada y luego al directorio de trabajo actual.

 // Check your default include path, most likely to be C:\xampp\php\PEAR echo get_include_path(); // To set include path set_include_path ( string $new_include_path ) : string 

El Directorio de trabajo actual se deriva de su script de llamada principal index.php.

 // The Current Working Directory can be checked echo getcwd(); 

En el primer ejemplo donde el archivo requerido “../f2/f2.php” es de f1.php

Tu código no funciona porque –

  1. PHP ignora la ruta especificada, ya que su nombre de archivo comienza con ../
  2. f1 / el propio directorio del script de llamada también se ignora.
  3. El directorio del analizador busca en el directorio principal para encontrar el archivo solicitado. El directorio de trabajo actual es el directorio raíz, esto es desde donde ha iniciado el script de trabajo index.php. El archivo no se encuentra en este directorio, se ha dado una ruta incorrecta.

Así obtienes el Error Fatal

En el segundo ejemplo, ha cambiado el directorio y desde f1.php require_once (“f2.php”).

Su código funciona porque –

  1. Esta vez no necesita (“f2.php”) ningún encabezado ../ o ./ Esta vez PHP comprueba la ruta de inclusión pero la encuentra allí, ya que no la ha definido y el archivo no reside en la ruta de inclusión predeterminada predeterminada.
  2. Esta vez el directorio del script f1.php es f1 /. y requiere que el archivo (“f2.php”) se encuentre en este directorio. PHP Esta vez revisa el archivo en este directorio y lo encuentra.
  3. PHP no tiene que verificar el directorio de trabajo como se encontró el archivo.

Por lo tanto, su código funciona bien!