Как включить файлы PHP, которые требуют абсолютного пути?
У меня есть структура каталогов, подобная следующей;
script.php
вкл /include1.php
вкл /include2.phpОбъекты /object1.php
Объекты /object2.phpмыло /soap.php
Теперь я использую эти объекты в обоих script.php
а также /soap/soap.php
Я мог бы переместить их, но я хочу такую структуру каталогов по определенной причине. При выполнении script.php
путь включения inc/include.php
и при выполнении /soap/soap.php
его ../inc
абсолютные пути работы, /mnt/webdev/[project name]/inc/include1.php...
Но это уродливое решение, если я захочу переместить каталог в другое место.
Так есть ли способ использовать относительные пути или способ программно генерировать "/mnt/webdev/[project name]/"
?
11 ответов
Это должно работать
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
include "$root/inc/include1.php";
Редактировать: добавлено улучшение от aussieviking
Вы можете использовать относительные пути. Пытаться __FILE__
, Это константа PHP, которая всегда возвращает путь / имя файла скрипта, в котором она находится. Итак, в soap.php
Вы могли бы сделать:
include dirname(__FILE__).'/../inc/include.php';
Полный путь и имя файла файла. Если используется внутри включения, возвращается имя включенного файла. Начиная с PHP 4.0.2,
__FILE__
всегда содержит абсолютный путь с разрешенными символическими ссылками, тогда как в более старых версиях он содержал относительный путь при некоторых обстоятельствах. (источник)
Другим решением было бы установить путь включения в файле httpd.conf или в файле.htaccess.
Взгляните на http://au.php.net/reserved.variables
Я думаю, что переменная, которую вы ищете: $_SERVER["DOCUMENT_ROOT"]
Вы можете определить константу с путем к корневому каталогу вашего проекта, а затем поместить его в начало пути.
Другой способ справиться с этим, который вообще устраняет необходимость включения, - это использовать функцию автозагрузки. Включение всего, что нужно вашему сценарию "На всякий случай", может снизить производительность. Если вы включаете все определения классов или интерфейсов и хотите загружать их только при необходимости, вы можете перегрузить __autoload()
Функция с вашим собственным кодом, чтобы найти соответствующий файл класса и загружать его только тогда, когда он вызывается. Вот пример из руководства:
function __autoload($class_name) {
require_once $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
Пока вы устанавливаете свои переменные include_path соответственно, вам больше не нужно включать файл класса снова.
Другой вариант, связанный с Кевином, это использование __FILE__
, но вместо этого замените имя файла php внутри него:
<?php
$docRoot = str_replace($_SERVER['SCRIPT_NAME'], '', __FILE__);
require_once($docRoot . '/lib/include.php');
?>
Я использовал это некоторое время. Единственная проблема, иногда у вас нет $_SERVER['SCRIPT_NAME']
, но иногда есть другая переменная похожая.
Я нашел, что это работает очень хорошо!
function findRoot() {
return(substr($_SERVER["SCRIPT_FILENAME"], 0, (stripos($_SERVER["SCRIPT_FILENAME"], $_SERVER["SCRIPT_NAME"])+1)));
}
Использование:
<?php
function findRoot() {
return(substr($_SERVER["SCRIPT_FILENAME"], 0, (stripos($_SERVER["SCRIPT_FILENAME"], $_SERVER["SCRIPT_NAME"])+1)));
}
include(findRoot() . 'Post.php');
$posts = getPosts(findRoot() . 'posts_content');
include(findRoot() . 'includes/head.php');
for ($i=(sizeof($posts)-1); 0 <= $i; $i--) {
$posts[$i]->displayArticle();
}
include(findRoot() . 'includes/footer.php');
?>
require(str_repeat('../',(substr_count(getenv('SCRIPT_URL'),'/')-1))."/path/to/file.php");
Я использую эту строку кода. Он возвращается к "вершине" дерева сайта, затем переходит к нужному файлу.
Например, допустим, у меня есть это дерево файлов:
domain.com/aaa/index.php
domain.com/bbb/ccc/ddd/index.php
domain.com/_resources/functions.php
Я могу включить файл functions.php, где бы я ни был, просто скопировав копию
require(str_repeat('../',(substr_count(getenv('SCRIPT_URL'),'/')-1))."/_resources/functions.php");
Если вам нужно использовать этот код много раз, вы можете создать функцию, которая возвращает str_repeat('../',(substr_count(getenv('SCRIPT_URL'),'/')-1))
часть. Затем просто вставьте эту функцию в первый файл, который вы включаете. У меня есть файл "initialize.php", который я включаю в самый верх каждой страницы php и который содержит эту функцию. В следующий раз, когда мне нужно будет включить файлы, я просто использую функцию path_back
):
require(path_back()."/_resources/another_php_file.php");
Я думаю, что лучший способ - это включить ваши включения в ваш путь включения PHP. Существуют различные способы сделать это в зависимости от ваших настроек.
Тогда вы можете просто обратиться к
require_once 'inc1.php';
из любого файла, независимо от того, где он находится: в ваших включаемых или доступных в сети файлах, или на любом уровне вложенных подкаталогов.
Это позволяет вам размещать включаемые файлы вне корневого каталога веб-сервера, что является наилучшей практикой.
например
site directory
html (web root)
your web-accessible files
includes
your include files
Также проверьте __autoload для ленивой загрузки файлов классов.
@Flubba, это позволяет мне иметь папки внутри моего включаемого каталога? плоские каталоги дают мне кошмары. поскольку весь каталог объектов должен находиться в каталоге inc.
Ах да, абсолютно. Так, например, мы используем один слой подпапок, как правило:
require_once('library/string.class.php')
Вы должны быть осторожны, слишком полагаясь на путь включения на сайтах с очень высоким трафиком, потому что php должен искать в текущем каталоге, а затем во всех каталогах на пути включения, чтобы увидеть, существует ли ваш файл, и это может замедлить работу. вещи, если тебя забивают.
Так, например, если вы делаете MVC, вы должны указать путь к директории вашего приложения в пути включения, а затем указать ссылку на вещи в форме
'model/user.class'
'controllers/front.php'
или что угодно.
Но, вообще говоря, он просто позволяет вам работать с действительно короткими путями в вашем PHP, которые будут работать из любой точки мира, и его гораздо легче читать, чем всю эту корневую малярную клавишу документа realpath.
Преимущество этих основанных на сценариях альтернатив, предложенных другими, заключается в том, что они работают где угодно, даже на общих блоках; установка пути включения требует немного больше усилий и усилий, но, как я уже говорил, вы можете начать использовать __autoload, который просто самый крутой.
Если вы собираетесь включить определенный путь в большинство файлов в вашем приложении, создайте глобальную переменную для вашей корневой папки.
define("APPLICATION_PATH", realpath(dirname(__FILE__) . '/../app'));
or
define("APPLICATION_PATH", realpath(DIR(__FILE__) . '/../app'));
Теперь эту Глобальную переменную "APPLICATION_PATH" можно использовать для включения всех файлов вместо вызова realpath() каждый раз, когда вы включаете новый файл.
EX:
include(APPLICATION_PATH ."/config/config.ini";
Надеюсь, поможет;-)