За последние 24 часа нас посетил 22681 программист и 1039 роботов. Сейчас ищут 586 программистов ...

Как правильно работать с include?

Тема в разделе "PHP для новичков", создана пользователем EndoCrinolog, 27 сен 2017.

  1. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Здравствуйте, уважаемые программисты.
    Час настал, и мне очень захотелось узнать, как же всё-таки правильно работать с данной функцией?
    На статью натыкался, где некий прогер объясняет, что сайт существует в виртуальном мире и реальном. Но мне это ничего не дало. Поэтому, задаю конкретный вопрос.
    Я планирую работать с АБСОЛЮТНЫМИ путями, которые на сервере (нечто вроде, home/логин/сервер/www/public_html/корень сайта)
    Допустим, в корне сайта у меня есть конфигуративный файл, куда заносятся абсолютно все переменные, константы и прочее. Допустим, его название будет config.php.
    Также, у меня есть папка конфиг (тоже находится в корне), в которой будут также лежать файлы с конфигурацией и которые подключаются внутрь файла config.php через include (тут вроде бы всё понятно: будет нечто вроде
    Код (Text):
    1. include "config/database.php"
    )
    Но а теперь главный вопрос.
    Допустим, в корне лежит папка projects, внутри которой лежит папка project1, а в ней, в свою очередь, лежит файл index.php.
    Как мне ПРАВИЛЬНО сделать include() файла конфигураций config.php внутрь файла index.php, чтобы путь к этому файлу ВСЕГДА был верным, несмотря на разные домены, сервера и хостинги его пребывания?
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    include прячет некие ошибки, скрипт продолжает работать.
    require стопорит если что - то не то
     
  3. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Это я знаю, это меня не волнует. Меня волнует корректность указанных путей
    --- Добавлено ---
    Просто, большинство решаемых мною задач осуществляются через cron. А в кроне не существует $_SERVER['DOCUMENT_ROOT'].
    И я подумал, что можно сделать так:
    1) Создать в корне файл config.php и прописать там
    Код (Text):
    1. define("ROOT", dirname(__FILE__));
    Таким образом, в файле конфига прописан абсолютный путь к корню сайта.
    2) Подключать файл config.php ко всем остальным файлам, которым необходимы конфигурации скрипта.

    Но тут встает вопрос: как нужно подключать это файл в скрипты, которые находятся не в корне, а поглубже, типа корень/папка1/папка2/папка3 ? Как другие скрипты в папках смогут узнать, какая папка будет являться корнем сайта, чтобы подключить конфиг? Неужели нет самой классной и адекватной константы, в которой просто будет содержаться путь до корня и она будет всегда одинакова не смотря на расположения в древе проекта?..........
     
  4. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    PHP:
    1. dirname ( __FILE__, INT... )
    причем тут тогда подключение, если вас волнует путь директории?
     
  5. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Опять-таки, это надо высчитывать этот самый уровень, чтобы получить доступ к корню.
    В общем, я уже вроде как придумал универсальный способ получить доступ к корню, без указания и высчитывания специфических данных из любого места сайта...
     
  6. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    в студию, посмотрим
     
  7. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Примерно такое решение родилось сегодня ночь. Данный скрипт позволяет найти путь к корню из любого места сайта:
    Код (Text):
    1. <?php
    2. $SCRIPT_DIR = rtrim((str_replace('\\', '/', realpath(dirname(__FILE__)))), '/') . '/';
    3. $CONFIG_DIR = 'config/Config.php';
    4. $INC_CONFIG = $SCRIPT_DIR . $CONFIG_DIR;
    5. while ( !file_exists($INC_CONFIG) )
    6. {
    7.     $SCRIPT_DIR = dirname($SCRIPT_DIR) . '/';
    8.     $INC_CONFIG = $SCRIPT_DIR . $CONFIG_DIR;
    9. }
    10. require_once $INC_CONFIG;
    11.  
    12. print_r($Config);
    13. ?>
    Конечно, может, крупно. Но тем не менее, я могу получить доступ к конфигу, указав только его расположение в $CONFIG_DIR. Конечно, решение зациклится, если данного файла существовать не будет. Но тем не менее, при одинаковой структуре проекта это решение, как мне кажется, универсально. Не придется прописывать заборы из '/../../../' и высчитывать уровень расположения файла.
    Если есть еще более короткий вариант нахождения пути к корню и к файлам в нем в частности - буду рад посмотреть!
     
  8. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Что скажете? Можно сделать короче? Лучше?
     
  9. askanim

    askanim Старожил

    С нами с:
    7 апр 2016
    Сообщения:
    2.201
    Симпатии:
    166
    Адрес:
    GABRIEL
    А у меня вот существует если написать крон вот таким образом:
    Код (Text):
    1. 0-59 * * * * wget -O - -q -t 1 http://ford.loc/error
    ключ wget тебе в помощь
    --- Добавлено ---
    Но честно я себе в голову вдолбить не могу, что у тебя там не получается, что ты пишешь какую то валасатую хрень.
    --- Добавлено ---
    это вообще полный аут. Корень сайта начинается там, где начинается его точка входа, а значит прямо в этом первом файлике ты создаёшь константу:
    PHP:
    1. define('ROOT', __DIR__);
    И привет, не важно куда потом пойдёт скрипт у сайта будет всегда ROOT это путь до директории с корнем.
     
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.551
    Симпатии:
    1.754
    И получаем ограничение в 30 секунд на выполнение задания. Не люблю этот способ.
    @EndoCrinolog, просто сделай консольную единую точку входа и радуйся.
     
  11. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Хорошо. Создали Вы этот файл, поместили туда этот код.
    Допустим, у вас есть от корня 3 вложенные папки: папка1/папка2/папка3/index.php
    Как получить доступ к константе ROOT из этого внутренного index.php?
     
  12. gruth

    gruth Активный пользователь

    С нами с:
    13 май 2017
    Сообщения:
    224
    Симпатии:
    18
    А константы с $_SERVER чем не угодили?
    В document_root будет путь к корню сайта, и вроде как везде это доступно
     
  13. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    А если крон? :)
     
  14. gruth

    gruth Активный пользователь

    С нами с:
    13 май 2017
    Сообщения:
    224
    Симпатии:
    18
    крон ведь пхп скрипты запускает?
     
  15. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    ну да.. но по сути-то, запуск через консоль.. а значит, там нет переменной document_root
    А как выразился mkramer
    А это недопустимо в моей ситуации.
     
  16. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Это я про wget
     
  17. gruth

    gruth Активный пользователь

    С нами с:
    13 май 2017
    Сообщения:
    224
    Симпатии:
    18
    Да, не заметил вовсе, так можно же сделать основной файл который в корне лежит. Там констант навешать, а подключать остальное через аргументы к этому файлу.
     
  18. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    Может быть я недостаточно ясно выражаю свою мысль....
    Смотрите, у нас есть корень сайта, который располагается по адресу: /home/hosting/userlogin/public_html/
    Отсюда у нас начинается вся движуха.Допустим, у нас в корне лежит файл с конфигурацией Config.php. Допустим, есть несколько директорий, которые также лежат внутри корня и содержат инструменты, которые подключаются внутри Config.php (тут всё понятно. схема такого подключения будет
    Код (Text):
    1. include "frameworkphp/database.php";
    2. include "frameworkphp/functions.php";
    ). Тут всё и так ясно.
    Но допустим, что есть также в корне несколько других директорий, которые работают вообще особняком. К примеру, папка admin, где содержатся инструменты администрирования. А внутри папки admin есть еще несколько папок с файлами, которые, к примеру, являются php-скриптами, получающие запросы с json-скриптов. К примеру /admin/configs/updateConfig.php.
    ВОТ В ТАКОМ СЛУЧАЕ, как файлу updateConfig.php подключаться к Config.php, чтобы иметь такой же доступ к БД, как и у корневых скриптов? В этом и есть вопрос моей темы. Потому что при изменении архитектуры все эти заборы из /../../../../.. просто перестают работать.. Или те же dirname(dirname(dirname($path))) становятся некорректными...
    Ок, может быть это прокатит с $_SERVER['DOCUMENT_ROOT'].
    Но вдруг у нас несколько cron-задач, расположенные в разных частях сайта. Тогда встает вопрос - как универсально получать доступ к корню, если DOCUMENT_ROOT не работает в кроне?
     
  19. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.744
    Симпатии:
    1.319
    Адрес:
    Лень
    есть
    но выводит корневой каталог крона
    --- Добавлено ---
    ничего личного, велосипед из говна слепили. Можно
    http://www.cyberforum.ru/php-beginners/thread741602.html
    --- Добавлено ---
    изобретатель:)
    http://phpfaq.ru/newbie/paths
     
  20. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.236
    Адрес:
    там-сям
    чтобы правильно использовать include (или require) достаточно помнить про две вещи. и они связаны между собой )))

    1. относительно какого места отсчитывается путь в include, если он указан относительно (т.е. НЕ начинается с "/")
    2. что является "текущей директорией"

    1. это зависит от настроек в php.ini. вот одна из причин справедливой ненависти и презрения человечества к пхп.
    есть такая настройка include_path. обычно она включает в себя и текущую директорию ".".
    значит с некоторой натяжкой можно считать, что путь до файла в include указывается относительно текущей директории

    2. осталось выяснить чему равна текущая директория. есть два варианта:
    2.а. если речь о веб-скрипте, который вы вызываете в браузере, то текущей директорией будет папка, в которой находится точка входа. то есть как правило это корневая папка вашего сайта.
    2.б. если речь о консольном скрипте, который вызывается "ручками из командной строки" или, например, из крона, то текущая директория может быть любой. то есть просто любой.
    когда вы ползаете в консоли по папкам, вызывая команду "cd имя_папки", вы меняете вашу текущую директорию. при этом вы можете обратиться к любому php файлу в этой или другой папке. текущая директория это ваша папка, а не папка со скриптом!

    НЮАНС: текущая директория НЕ ИЗМЕНЯЕТСЯ в приинклуженных файлах. поясню на примере:
    есть файлы:
    /home/vasinsait/www/index.php
    /home/vasinsait/www/app/helpers/arr.php
    /home/vasinsait/www/lib/hujnane/qwerty.php

    предположим, что index - это точка входа на сайт, в нём текущая директория это "/home/vasinsait/www".
    допустим в этом файле инклудится другой файл
    PHP:
    1. include "app/helpers/arr.php";
    . как думаете, внутри app.php текущая директория это "/home/vasinsait/www/app/helpers"? автофиг! она по прежнему "/home/vasinsait/www". и если вам надо инклудить файл qwerty, то вот так сработает:
    PHP:
    1. include "lib/hujnane/qwerty.php";
    независимо от того, где находится сам оператор include — в index или в arr.php.
    --- Добавлено ---
    P.S. волшебная константа __DIR__ не зависит от "текущей директории". она содержит путь до папки с этим конкретным скриптом. то есть она разная для "…/app/helpers/arr.php" и для "…/lib/hujnane/qwerty.php".
    кроме того, так как значение в __DIR__ абсолютный путь, а не относительный, если вы начнёте include с неё, то настройка include_path остсасывает.
    из "app/helpers/arr.php" обращаемся к "lib/hujnane/qwerty.php" с помощью __DIR__:
    PHP:
    1. include __DIR__."/../../lib/hujnane/qwerty.php";
    т.к. данный способ не зависит от "текущей директории", то он будет одинаково хорошо работать и для веб, и для консольного вызова.
     
    mahmuzar и EndoCrinolog нравится это.
  21. EndoCrinolog

    EndoCrinolog Активный пользователь

    С нами с:
    4 фев 2012
    Сообщения:
    205
    Симпатии:
    1
    Адрес:
    Тольятти
    То есть, я так понимаю, остается городить заборы? А насчет этого что скажете?
    Код (Text):
    1. <?php
    2. $SCRIPT_DIR = rtrim((str_replace('\\', '/', realpath(dirname(__FILE__)))), '/') . '/';
    3. $CONFIG_DIR = 'config/Config.php';
    4. $INC_CONFIG = $SCRIPT_DIR . $CONFIG_DIR;
    5. while ( !file_exists($INC_CONFIG) )
    6. {
    7.     $SCRIPT_DIR = dirname($SCRIPT_DIR) . '/';
    8.     $INC_CONFIG = $SCRIPT_DIR . $CONFIG_DIR;
    9. }
    10. require_once $INC_CONFIG;
    11. print_r($Config);
    12. ?>
     
  22. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.551
    Симпатии:
    1.754
    В чём проблема сделать единую точку входа для консольного приложения? И тогда не надо ничего городить.
     
    artoodetoo нравится это.
  23. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.236
    Адрес:
    там-сям
    я совсем другой смысл вкладывал в свой "мануал" :D

    вот именно. зачем эти огороды?! :) единая точка входа, и автолоадер избавляют ваш код от инклудов в принципе.
    а для всяких поделок из пяти файлов хватит указания путей через __DIR__.
     
  24. Danil005

    Danil005 Активный пользователь

    С нами с:
    2 янв 2015
    Сообщения:
    528
    Симпатии:
    30
    Кстати, зачем использовать "волшебные константы", если можно тупо делать так: '../../file';
    По сути, если использовать эти константы, все равно нужно будет делать так.

    Почему не используют $_SERVER['DOCUMENT_ROOT']?
     
  25. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.551
    Симпатии:
    1.754
    Потому что речь про CLI идёт.
    @artoodetoo же объяснил. Почему нежелательны относительные пути в include