2008-12-23 14 views
6

Este es un problema con el que me he encontrado recientemente: un apache mal configurado en un servidor de Internet. Esto significa que todos los scripts que se basan en $_SERVER['DOCUMENT_ROOT'] se rompen. La solución más fácil que he encontrado es simplemente configurar la variable en algunos archivos globales de inclusión que se comparten, pero es un dolor no olvidarlo. Mi pregunta es, ¿cómo determino la raíz correcta del documento programáticamente?¿Cómo determinar programáticamente la raíz del documento en PHP?

Por ejemplo, en un host, la configuración es la siguiente:

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

las raíces reales de documento son:

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

y me gustaría una secuencia de comandos que se ejecuta desde www.example.com/blog/ (en la ruta /data/htdocs/example.com/www/blog) para obtener el valor correcto de /data/htdocs/example.com/www.

En otro host, la configuración es un poco diferente:

$_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 

¿Hay alguna solución para esto? ¿O es la única forma de no confiar nunca en $_SERVER['DOCUMENT_ROOT'] y arreglar todo el software que estoy ejecutando en mis sitios? Reparar esto en el lado del servidor no parece ser una opción, todavía tengo que encontrar un host donde esto se haya configurado correctamente. Lo mejor que obtuve fue una raíz de documento que apuntaba a www.example.com, que al menos estaba dentro de open_basedir; usaban otro esquema de nombres, www.example.com apuntaría al /u2/www/example_com/data/www/.

Respuesta

2

Basado en http://www.helicron.net/php/:

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

Tuve que cambiar el truco de basename/realpath porque devolvía una cadena vacía en mi host. En cambio, uso SCRIPT_FILENAME. Probablemente esto ya no funcione en IIS (pero los scripts originales que usaron la variable $ _SERVER probablemente tampoco).

0

PHP debe ser la creación del directorio actual a la que el guión se encuentra, así que mientras que no está roto debe ser capaz de averiguar la raíz del documento usando $_SERVER['SCRIPT_FILENAME'] y getcwd(). (No puedo recordar todos los $ _SERVER vars de la parte superior de mi cabeza, podría haber algo en phpinfo() que sea más útil.)

+0

Algunos scripts que he instalado son "demasiado inteligentes" y saben en qué directorio (relativo a la raíz del documento teórico) están instalados, y anexan esto al documento raíz (después de que lo obtuvieron de la base de datos). Todavía tendría que modificar el código de cada directorio para quitar los directorios ... ¿o no? –

7

En PHP5 hay la constante mágica __FILE__ que contiene la ruta absoluta del archivo en el que aparece. Puede usarlo en combinación con dirname para calcular la raíz del documento.

Se puede retener una declaración como la siguiente en un archivo de configuración

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

esto debe hacer el truco

+1

El truco fue usar tanto el nombre absoluto del archivo (ya sea de la constante mágica, o de los valores del servidor) y combinarlo con el conocimiento de la ruta de acceso absoluta a la raíz del documento de SCRIPT_NAME. –

+3

Desde PHP 5.3 esto también es '__DIR__' usar eso en lugar de' dirname (__ FILE __) '. – Michael

+0

Pero esto solo devuelve la carpeta del archivo actual que no es necesariamente la carpeta raíz real del servidor web. – Chuck

3

No hay necesidad de modificar todos los scripts.

Puede ejecutar el archivo PHP antes de ejecutar cualquier script usando auto_prepend_file.

$_SERVER es sólo una matriz, puede modificarlo y establecer correcta $_SERVER['DOCUMENT_ROOT'].

+0

Es inútil ejecutar ese script en * cada ejecución. – SchizoDuckie

+0

Es inútil ejecutar ese script en * every * run. Mejor manejarlo con algunos .htaccess en lugar de configurarlo. – SchizoDuckie

+0

Puede usar php_value en .htaccess para establecer auto_prepend_file, pero el autor de la pregunta mencionó el servidor IIS, que supongo que no es compatible con esto. – Kornel

0

¿Por qué no exige que su servidor web configure correctamente sus servidores?

este tipo de cosas tienden a permanecer en silencio en su código y nunca se eliminan (pero siguen activas) hasta que alguien finalmente arregle el servidor. Todo se romperá de nuevo.

O mueva sus cosas a un host que funcionará. Si esto no funciona, quién sabe qué encontrarás a continuación.

+0

No estoy seguro si es posible configurar el host correctamente, parece ser un problema con mod_vhost_alias (según un comentario en http://www.webmasterworld.com/apache/3640691.htm). –

2

Esta es una de las razones por las que las personas hacen un sifón a través de bootstrap /index.php usando htaccess y/o cadenas de consulta. Puede usar el truco dirname(__FILE__) que se menciona arriba y obtener la base pública de su aplicación de esa manera.

Si está demasiado lejos para cambiar a un único punto de entrada, una cosa que he visto hacer a la gente es tener un encabezado común en su script que recorre el árbol de directorios para encontrar un archivo que es exclusivo de el directorio de la base:

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

    return findAppBase(dirname($dir)); 
} 

$base = findAppBase(dirname(__FILE__)); 

ese código no ha sido probado, y puede haber una manera más pulido utilizando los VARs en $_ENV o $_SERVER que va a hacer lo que quiere ...

+0

Afortunadamente, esto no es un problema, solo tengo un solo punto de entrada. Es solo que ejecuto el mismo software en múltiples dominios y hosts, y tengo que arreglarlo para cada dominio. Prefiero enviar un arreglo en sentido ascendente para que ya no tenga que preocuparme por eso. –

Cuestiones relacionadas