include vs require в PHP: разница, примеры и лучшие практики
Один из первых вопросов в PHP — как правильно подключать файлы. В ход идут четыре конструкции: include, require, include_once и require_once. Кажется просто, но у каждой — своя семантика, влияние на ошибки, производительность и безопасность.
Что делают include и require
Обе конструкции «вклеивают» PHP‑файл в текущий во время выполнения: код подключаемого файла компилируется и выполняется в той же области видимости, что и место вызова.
<?php
// basic.php
include 'header.php';
eccho 'Привет!'; // опечатка вызовет ошибку на этой строке
include 'footer.php';
Главное отличие — реакция на ошибку при отсутствии файла:
- include — генерирует предупреждение (E_WARNING), скрипт продолжит работу;
- require — генерирует фатальную ошибку (E_ERROR), выполнение прервётся.
Разница include vs require на примере
<?php
$file = 'config.php';
include $file; // Если файла нет — предупреждение и скрипт продолжит выполняться
echo "Дальше работаем...\n";
require $file; // Если файла нет — фатальная ошибка, скрипт остановится
echo "Эта строка не выполнится, если файла нет";
Практическое правило: критически важные зависимости (конфиг, автозагрузка, константы) подключайте через require, опциональные блоки (например, виджеты) — через include.
include_once и require_once
Варианты с суффиксом _once подключают файл только один раз за выполнение скрипта. Это удобно для файлов с объявлениями функций/классов, чтобы избежать «Cannot redeclare…».
<?php
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/config.php';
include_once __DIR__ . '/helpers.php';
Минус: _once стоит немного дороже обычного include/require из‑за проверки, подключался ли файл ранее. Не вызывайте *_once в циклах — вынесите в точку входа (bootstrap). В проектах с OPCache разница небольшая, но правило остаётся актуальным для чистоты архитектуры.
Правильные пути: __DIR__ и относительные подключения
Частая ошибка новичков — полагаться на «текущую рабочую директорию» (getcwd), которая меняется в зависимости от точки входа (CLI, фронт‑контроллер, крон). Безопаснее формировать абсолютные пути от директории файла, в котором вы пишете include/require:
<?php
// Надёжный способ
require __DIR__ . '/config/config.php';
// Если файл на уровень выше
require dirname(__DIR__) . '/bootstrap.php';
// Для глубокой структуры
require realpath(__DIR__ . '/../app/Routes.php');
Альтернатива — настраивать include_path (php.ini или set_include_path), но для начинающих проще и прозрачнее использовать __DIR__ и dirname().
<?php
// Пример с include_path (опционально)
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/lib');
include 'Utils.php'; // теперь ищется в ./lib
Можно ли «вернуть значение» из подключаемого файла?
Да. Результат include/require — это значение, которое вернул подключаемый файл оператором return. Удобно для конфигов.
<?php
// config/db.php
return [
'dsn' => 'mysql:host=localhost;dbname=app;charset=utf8mb4',
'user' => 'root',
'pass' => 'secret',
];
// index.php
$db = require __DIR__ . '/config/db.php';
$pdo = new PDO($db['dsn'], $db['user'], $db['pass']);
Если файл ничего не вернул, include/require возвращает 1 при успехе и false при неудаче (для include).
Область видимости: переменные «протекают»
Подключаемый файл выполняется в текущей области видимости. Он видит локальные переменные вызывающего контекста и может их изменять, а его переменные станут доступны после include/require. Это удобно, но может привести к неожиданностям. Изолируйте подключение в функцию, когда нужно скрыть переменные.
<?php
// layout.php
$title = 'Главная';
$content = '<p>Добро пожаловать</p>';
require __DIR__ . '/view.php'; // view.php увидит $title и $content
// Изоляция операций рендеринга
function render($tpl, array $vars = []) {
extract($vars, EXTR_SKIP);
require __DIR__ . '/views/' . $tpl . '.php';
}
render('home', ['title' => 'Дом', 'content' => '<p>Текст</p>']);
Безопасность: никогда не подключайте то, что пришло от пользователя
Главное правило — не подставляйте в include/require значения из GET/POST/COOKIE/файлов без строгой валидации. Используйте белый список маршрутов/шаблонов, а не «динамические пути». Обязательно держите allow_url_include = Off (по умолчанию так и есть).
<?php
// Плохо ❌
$view = $_GET['view'] ?? 'home';
require __DIR__ . "/views/{$view}.php"; // RFI/LFI уязвимость
// Хорошо ✅ — белый список
$views = [
'home' => 'home.php',
'about' => 'about.php',
];
$view = $_GET['view'] ?? 'home';
$file = $views[$view] ?? $views['home'];
require __DIR__ . '/views/' . $file;
Производительность и структура проекта
- Не используйте *_once в циклах и часто вызываемых функциях — подключайте ключевые файлы один раз в bootstrap (public/index.php).
- Включите и настройте OPCache в продакшене — он кэширует байткод и уменьшает накладные расходы на подключения.
- Соберите «точки входа»: один файл окружения (require config.php), один автозагрузчик, один роутер — меньше include‑хаоса, проще отладка.
Частые ошибки и как их избежать
- Header already sent — лишние пробелы/строки в подключаемом файле до <?php. Уберите BOM и пробелы.
- Cannot redeclare function/class — дубль подключения. Примените require_once или пересмотрите архитектуру.
- Файл не найден в кроне/CLI — относительные пути. Используйте __DIR__ или абсолютные пути от корня проекта.
- Смешение слэшей на Windows/Linux — формируйте пути через DIRECTORY_SEPARATOR или просто используйте прямой слэш «/», который поддерживается PHP кроссплатформенно.
Мини‑шпаргалка выбора
- require — обязательная зависимость, без неё выполнение невозможно.
- include — необязательный блок (баннер, виджет, экспериментальная панель).
- *_once — для деклараций (классы, функции), чтобы избежать повторного подключения.
- Пути — через __DIR__/dirname(), не через относительные «на авось».
- Безопасность — только белые списки и жёстко заданные пути.
Что дальше изучать
Если хотите системно прокачать PHP и научиться строить проекты с нуля до продакшена, обратите внимание на практический курс: Пройти практический курс «PHP и MySQL с Нуля до Гуру 3.0». Много практики, современные подходы и поддержка.
Теперь вы уверенно различаете include и require, понимаете, когда нужны варианты *_once, как правильно указывать пути и не попадать в ловушки безопасности. Этого уже достаточно, чтобы собирать аккуратную структуру проекта и избежать типичных багов новичков.
-
Создано 27.03.2026 17:01:30
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.