ФорумПрограммированиеПыхнуть хотите?F.A.Q. → Указание пути к подключаемому файлу

Указание пути к подключаемому файлу

  • vasa_c

    Сообщения: 3131 Репутация: N Группа: в ухо

    Spritz 13 августа 2007 г. 10:17

    При использовании include/require, а так же других файловых функций, требуется указывать путь к файлу.
    Пути бывают двух видов: абсолютные и относительные.

    Абсолютный путь указывает путь к файлу от корня файловой системы:
    /home/user/file - в Unix'е корень обозначается как "/".
    C:\Folder\file.txt - в Windows корнем является имя диска.


    Относительный путь указывает файл относительно текущего каталога:
    script.php - файл в текущем каталоге
    ./script.php - тоже самое, "." обозначает текущий каталог
    ./folder/script.php - файл находится в каталоге folder, являющимся подкаталогом текущего
    ../script.php - файл находится в каталоге, являющимся родительским для текущего
    ./../folder/script.php - файл из каталога folder, находящимся в одном родительском каталоге вместе с текущим.


    Каждый исполняющийся сценарий имеет связанный с ним текущий каталог, относительно которого и разруливаются относительные пути. Текущим каталогом назначается каталог в котором хранится файл сценария. В процессе работы он может быть изменен с помощью функции chDir().

    Очень важно понимать, что является исполняющимся сценарием.
    Например, запрашиваем из браузера документ httр://site.ru/script.php. web-сервер находит соответствующий ему сценарий, допустим /home/site.ru/www/script.php. Запускает его. В сценарии есть инструкция:
    require_once('./folder1/file1.php');

    В файле file1.php есть строчка:
    require_once('./folder2/file2.php');


    То есть изначальный файл подключает другой файл, а тот, в свою очередь, третий.

    Так вот, подобных включений может быть сколько угодно и какой угодно может быть степень вложенности. Однако, исполняемый сценарии (процесс операционной системы) будет только один - изначальный сценарий /home/site.ru/www/script.php. А текущим каталогом будет /home/site.ru/www/. Будет на всем протяжении сценария, вне зависимости от require().

    Таким образом, при выполнении require_once('./folder2/file2.php') папка folder2 будет искаться не в папке folder1, где лежит file1.php, а в папке изначального сценария - /home/site.ru/www/.

    От непонимания данной вещи очень часто случаются сложноуловимые ошибки. Что же делать, как избежать геморроя при указании пути? Рецептов несколько.


    Изменение текущего каталога

    Перед каждым require() изменять текущий каталог при помощи chDir() на каталог подключаемого файла. Старое значение сохранять в какой-либо переменной (желательно в стеке) и восстанавливать после require().

    Данное решение я привел "до кучи". Несоменно, заниматься подобным маразмом не стоит.


    Указание путей относительно текущего каталога

    Если использующий require() сценарий может быть только исполняемым (вызываться из браузера, но не подключаться через require) такой вариант вполне рабочий.

    Если сценарий может подключаться только из одного исполняемого файла (или возможные исполняемые файлы лежат в одном каталоге), то данный вариант так же прокатывает.

    Однако, если файл может подключаться из разных мест, то так не получится, т.к. текущий каталог может быть каждый раз разным.


    Указание абсолютных путей
    Собственно наиболее верный и наиболее распространенный способ. Однако, и здесь могут быть варианты.

    Можно каждый раз прописывать путь явно:
    require('/home/site.ru/www/folder1/file1.php');
    require('/home/site.ru/www/folder2/file2.php');

    Но так можно запариться прописывать и тем более перепрописывать в случае изменения.

    Можно вынести в конфиг:

    define('DIR_WWW', '/home/site.ru/www/');

    require(DIR_WWW.'/folder1/file1.php');
    require(DIR_WWW.'/folder2/file2.php');

    Многие так и делают. И зря. Так как опять таки затруднен перенос из папки в папку, с сервера на сервер. Каждый раз придется отыскивать все подобные дефайны и исправлять.

    В PHP есть предопределенная переменная $_SERVER['DOCUMENT_ROOT'], которая содержит путь к корневой папке сайта. Лучше всего плясать от нее:

    require($_SERVER['DOCUMENT_ROOT'].'/folder1/file1.php');
    require($_SERVER['DOCUMENT_ROOT'].'/folder2/file2.php');


    Использование DOCUMENT_ROOT является наиболее разумным способом при подключении различных частей сайта из главного файла или из других частей.

    Однако для указания файлов внутри какой-то отдельной части (модуля) этот способ не совсем удобен.
    Например, вы пишите библиотеку состоящую из нескольких файлов и подключающих друг друга. Она может использоваться на множестве сайтов и располагаться в различных каталогах. Очевидно, что здесь гораздо лучше привязываться не к корню сайта, а к местоположению самих файлов библиотеки. Здесь может помочь "магическая" константа __FILE__. Она содержит абсолютный путь к текущему обрабатываемому файлу, т.е. к файлу в котором используется. Таким образом, подключение файла расположенного в том же каталоге, что и подключающий:
    require_once(dirName(__FILE__).'/file.php');
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 18 августа 2007 г. 12:11, спустя 5 дней 1 час 53 минуты

    Также можно использовать include_path

    set_include_path();
    Только для PHP 4 >= 4.3.0, PHP 5

    <?php

    if(!defined( "PATH_SEPARATOR" )) {
    if(strpos( $_ENV[ "OS" ], "Win" ) !== false ) {
    define( "PATH_SEPARATOR", ";" );
    } else {
    define( "PATH_SEPARATOR", ":" );
    }
    }

    $path = '/home/user/siteru/www/libdir/';

    set_include_path(get_include_path() . PATH_SEPARATOR . $path);

    ?>


    ini_set();
    Для всех версий PHP

    ini_set('include_path', '/inc');
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • rrur007

    Сообщения: 1 Репутация: N Группа: Кто попало

    Spritz 29 июня 2012 г. 2:05, спустя 1776 дней 13 часов 54 минуты

    Если извращацо, таки пополной.
    вот еще метод как подключить файл находящийся на уровень выше т.е. родительским для текущего файла

    require_once(dirName(__FILE__).'/../file.php');

    require_once(dirName(__FILE__).'/../dirname/file.php');

  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 29 июня 2012 г. 3:53, спустя 1 час 47 минут 13 секунд

    Чуть-чуть до 5 лет не хватило, поздравляю!
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • vasa_c

    Сообщения: 3131 Репутация: N Группа: в ухо

    Spritz 29 июня 2012 г. 4:19, спустя 26 минут 41 секунду

    Чуть-чуть до 5 лет не хватило, поздравляю!

    никогда не поздно узнать что-то новое )

Пожалуйста, авторизуйтесь, чтобы написать комментарий!