Я знаю, что на это ответили и приняли, но я не видел, чтобы кто-нибудь вмешивался в то, почему это решение сработало и что изначально было неправильным.
Краткое описание проблемы
Текущий рабочий каталог устанавливается в момент, когда php получает запрос, и все относительные пути разрешаются на основе текущего рабочего каталога, а не каталога файла, на который ссылается путь.
Подробное описание проблемы
Относительные пути в php разрешаются на основе текущего рабочего каталога.
В целях тестирования вы всегда можете увидеть текущий рабочий каталог, вызвав getcwd.
Это значение изначально получено в HTTP-запросе как каталог, содержащий файл, который веб-сервер изначально передал запрос в php.
Так, например, если вы перейдете на http://www.mydomain.com/index.php, текущий рабочий каталог будет таким же, как корень документа ($_SERVER["DOCUMENT_ROOT"]
)
Для запроса CLI cwd — это каталог, в котором вы находитесь, когда выполняете команду. Итак, если я нахожусь в /home/orangepill
и запускаю /usr/bin/php /path/to/file.php
, cwd будет /home/orangepill
.
Это вызывает проблему для относительных ссылок на файлы во включенных файлах.
Возьмем этот пример.
Клиент переходит на www.mydomain.com
Apache имеет index.php, установленный в директиве DirectoryIndex, и apache находит файл index.php в корне документа. Текущий рабочий каталог установлен в корень документа.
/index.php содержит строку include "library/myclass.php";
$_SERVER["DOCUMENT_ROOT"]."/library/myclass.php" существует и все хорошо
myclass.php содержит строку include("myclass_helper.php");
, которая разрешается в $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php". (помните, что относительные ссылки разрешаются относительно текущего рабочего каталога)
$_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php"
не существует на самом деле в $_SERVER["DOCUMENT_ROOT"]."/library/myclass_helper.php"
Вы, вероятно, что-то, но подождите ... Я испытал различное поведение в своих сценариях при включении в включение. Причина этого в том, что языковые конструкции include и require (наряду с парой других команд файловой системы) пытаются включить относительные пути из каждого из путей, указанных в директиве include path php. Таким образом, в приведенном выше примере, если каталог библиотеки вне корня документа существует в путях включения, тогда все будет работать так, как ожидалось.
Полное решение для запроса файлов относительно текущего файла состоит в том, чтобы структурировать пути включения с помощью контекстной константы __DIR__
. Таким образом, вы должны использовать include __DIR__."/myclass_helper.php";
(include dirname(__FILE__)."/myclass_helper.php
в средах до PHP 5.3), и во время выполнения это эффективно преобразует ваш относительный путь в абсолютный путь на основе местоположения файла, выполняющего включение.
Для общих включаемых каталогов у меня есть привычка указывать несколько часто используемых местоположений для использования с относительными ссылками файловой системы. Например
define ("APPLICATION_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/application");
define ("LIBRARY_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/library");
define ("CONFIG_PATH", APPLICATION_PATH."/etc/";
Это дает вам много опорных точек для включения путей относительно них.
person
Orangepill
schedule
13.07.2013