Включают ли PHP пути относительно файла или вызывающего кода?
У меня возникли проблемы с пониманием набора правил, касающихся относительных путей включения PHP. Если я запущу файл A.PHP - и файл A.PHP включает файл B.PHP который включает в себя файл C.PHP, должен ли относительный путь к C.PHP быть по отношению к местоположению B.PHP, или к месту нахождения A.PHP? То есть, имеет ли значение, из какого файла вызывается включение, или только из текущего рабочего каталога - и что определяет текущий рабочий каталог?
6 answers
В данном случае это относительно основного сценария A.php . Помните, что include()
просто вставляет код в текущий запущенный скрипт.
То есть, имеет ли значение, из какого файла вызывается включение
Нет.
Если вы хотите сделать это важным и включить относительно B.php , используйте константу __FILE__
(или __DIR__
начиная с PHP 5.2 IIRC), которая всегда будет указывать на буквальный текущий файл, в котором находится строка кода.
include(dirname(__FILE__)."/C.PHP");
@Пекка привел меня туда, но просто хочу поделиться тем, что я узнал:
getcwd()
возвращает каталог, в котором находится файл, который вы начали выполнять.
dirname(__FILE__)
возвращает каталог файла, содержащего выполняемый в данный момент код.
Используя эти две функции, вы всегда можете построить путь включения относительно того, что вам нужно.
Например, если b.php и c.php общий доступ к каталогу, b.php может включать c.php например:
include(dirname(__FILE__).'/c.php');
Независимо от того, где b.php был вызван из.
На самом деле, это предпочтительный способ установления относительных путей, так как дополнительный код освобождает PHP от необходимости перебирать include_path в попытке найти целевой файл.
Источники:
Разница между getcwd() и dirname(__ФАЙЛ__)? Что я должен использовать?
-
Если путь включения не начинается с
./
или../
, например:include 'C.php'; // precedence: include_path (which include '.' at first), // then path of current `.php` file (i.e. `B.php`), then `.`.
-
Если путь включения начинается с
./
или../
, например:include './C.php'; // relative to '.' include '../C.php'; // also relative to '.'
.
или ..
выше относится к getcwd()
, который по умолчанию указывает путь к файлу записи .php
(т. е. A.php
).
Протестировано на PHP 5.4.3 (Дата сборки: Май 8 2012 00:47:34).
(Также обратите внимание, что chdir()
может изменить вывод getcwd()
.)
Принятый ответ Пекки является неполным и, в общем контексте, вводящим в заблуждение. Если файл указан как относительный путь, вызываемая языковая конструкция include
будет искать его следующим образом.
Сначала он пройдет по путям переменной среды include_path
, которую можно задать с помощью ini_set
. Если это не удастся, он будет искать в собственном каталоге вызывающего скрипта dirname(__FILE__)
(__DIR__
с php>=5.3.) Если это также не удастся, только тогда он будет искать в рабочем справочник! Просто оказывается, что по умолчанию переменная среды include_path
начинается с .
, которая является текущим рабочим каталогом. Это единственная причина, по которой он сначала выполняет поиск в текущем рабочем каталоге. См. http://php.net/manual/en/function.include.php .
Файлы включаются на основе указанного пути к файлу или, если он не указан, указанного пути include_path. Если файл не найден в include_path, include, наконец, проверит вызывающий собственный каталог скрипта и текущий рабочий каталог до сбоя.
Итак, правильный ответ на первую часть вопроса заключается в том, что имеет значение, где находится включенный вызывающий скрипт. Ответ на последнюю часть вопроса заключается в том, что начальный рабочий каталог в контексте веб-сервера является каталогом вызываемого скрипта, скрипта, который включает в себя все остальные при обработке PHP. В контексте командной строки начальная рабочая каталог - это то, что есть, когда php вызывается в командной строке, не обязательно каталог, в котором находится вызываемый скрипт. Однако текущий рабочий каталог может быть изменен во время выполнения с помощью функции PHP chdir
. См. http://php.net/manual/en/function.chdir.php.
Этот абзац добавлен для комментариев к другим ответам. Некоторые упоминали, что полагаться на include_path
менее надежно, и поэтому предпочтительнее использовать полные пути, такие как ./path
или __DIR__ . /path
. Некоторые зашел так далеко, что сказал, что полагаться на сам рабочий каталог .
небезопасно, потому что его можно изменить. Однако иногда вам нужно полагаться на ценности окружающей среды. Например, вам может потребоваться установить include_path
пустым, чтобы каталог вызывающего скрипта был первым местом, в котором он будет искать, даже до текущего рабочего каталога. Код может быть уже написан и регулярно обновляться из внешних источников, и вы не хотите повторно вставлять префикс __DIR__
каждый раз, когда код обновленный.
Короткий ответ: это относительно сценария включения.
TFM объясняет это правильно:
Если файл не найден в include_path, include проверит каталог вызывающего скрипта и текущий рабочий каталог
Итак, если /app/main.php говорит include("./inc.php")
, что найдет /app/inc.php.
В ./ не является строго необходимым, но устраняет любую зависимость от include_path.
Я бы не стал полагаться на поиск файлов включения в текущем рабочем каталоге на случай, если кто-то изменит его с помощью chdir()
.
dir
-> a.php
-> c.php
- dir2
-> b.php
Чтобы включить a
в b
, вам необходимо include("../a.php");
Чтобы включить b
в c
, вам необходимо include("dir2/b.php");