Передача значений URL в подключаемые скрипты

Раздел: Основы PHP -> Работа с файлами

При работе с PHP часто требуется подключить один файл внутри другого и передать ему некоторые данные. Один из распространённых запросов - использование include с GET-параметрами. Однако функция include не обрабатывает URL-строку запроса: попытка написать include('file.php?param=value') приведёт к ошибке, так как PHP будет искать файл с буквальным именем «file.php?param=value». Рассмотрим разные способы передачи параметров в подключаемые файлы и разберём их плюсы, минусы и типичные проблемы.

Основные подходы к передаче параметров

Как надёжно передать переменные в подключаемый файл?

Самый эффективный и безопасный метод - объявить переменные перед вызовом include и использовать их внутри включаемого файла. Этот подход не затрагивает суперглобальный массив $_GET и даёт полный контроль над данными.

// index.php
$page = $_GET['page'] ?? 'home';
$allowed_pages = ['home', 'about', 'contact'];

if (in_array($page, $allowed_pages, true)) {
    include 'pages/' . $page . '.php';
} else {
    include 'pages/error.php';
}

Пояснение: Здесь используется белый список разрешённых страниц, что предотвращает атаки типа Local File Inclusion (LFI). Переменная $page будет доступна в подключаемом файле. Если параметр не передан или неверен, подключается страница ошибки.

Возможная проблема: прямое использование $_GET['page'] в include без проверки - частая ошибка, ведущая к уязвимости LFI.
Решение: всегда проверять значение через белый список, basename() или realpath().

Как сделать так, чтобы подключаемый файл использовал оригинальный $_GET?

Иногда подключаемый файл написан в расчёте на суперглобальный массив $_GET. В этом случае можно временно установить нужные элементы массива.

// index.php
$_GET['user_id'] = 42;
include 'profile.php'; // внутри profile.php используем $_GET['user_id']

После подключения массив $_GET останется изменённым. Это может привести к неожиданным побочным эффектам в остальном коде.

Проблема: изменение глобального массива влияет на все последующие операции, например, на другие include или скрипты.
Решение: сохранять и восстанавливать оригинальные значения, либо отказаться от этого метода в пользу локальных переменных.

Почему не работает include('file.php?x=1')?

Многие новички пытаются передать параметры прямо в строке пути. Это неверно: include ожидает локальный путь к файлу, а не URL.

// Неправильно
include 'config.php?mode=test';

Браузер выдаст предупреждение: Warning: include(config.php?mode=test): Failed to open stream. PHP ищет файл с именем «config.php?mode=test» в текущей директории.

Типичная ошибка: путаница с функции file_get_contents, которая может принимать URL. include же предназначена для включения локальных файлов.
Решение: использовать передачу переменных, как описано в базовом варианте.

Как передать много переменных в подключаемый шаблон?

Если требуется передать множество параметров, удобно использовать функцию с extract.

function renderTemplate(string $file, array $data): void {
    extract($data, EXTR_SKIP); // не перезаписывать существующие переменные
    include $file;
}

renderTemplate('user_card.php', [
    'name' => 'Иван',
    'age' => 30,
    'city' => 'Москва'
]);

Внутри user_card.php будут доступны переменные $name, $age, $city.

Проблема: extract может перезаписать существующие переменные, если не использовать флаги.
Решение: применять EXTR_SKIP или явно проверять имена ключей.

Можно ли передать GET-параметры через удалённый include?

При включении удалённого файла (allow_url_include включена) параметры можно передать в URL.

include 'http://example.com/handler.php?action=view';

Удалённый сервер получит GET-запрос с параметром action=view.

Проблемы: низкая производительность, уязвимости, зависимость от внешнего сервера. Функция allow_url_include часто отключена по соображениям безопасности.
Решение: по возможности избегать удалённого include, использовать локальные вызовы или cURL.

Как безопасно подключать файлы по GET-параметру?

Опасный, но иногда применяемый способ - динамическое имя файла из $_GET. Чтобы избежать LFI, используются проверки.

$file = basename($_GET['file']); // удалить пути
if (file_exists('includes/' . $file)) {
    include 'includes/' . $file;
}

Функция basename удаляет все компоненты пути, оставляя только имя файла.

Недостаток: всё ещё можно подставить, например, файл .htaccess или config.php.
Лучшее решение: использовать белый список, как в базовом методе.

Расширенные примеры с пояснениями

Пример 1. Динамическая загрузка модулей с белым списком

Полный пример безопасной загрузки контента на основе GET-параметра.

Пример
// index.php
$module = $_GET['mod'] ?? 'dashboard';
$allowed_modules = ['dashboard', 'users', 'settings', 'reports'];

if (!in_array($module, $allowed_modules, true)) {
    $module = 'dashboard';
}

// Передача дополнительных данных
$title = 'Панель управления';

include "modules/{$module}.php";

В файле modules/dashboard.php могут использоваться переменные $title, $module.

// modules/dashboard.php (пример содержимого)
<h1><?php echo $title; ?></h1>
<p>Вы выбрали модуль: <?php echo $module; ?></p>

Результат при запросе ?mod=dashboard:

<h1>Панель управления</h1>
<p>Вы выбрали модуль: dashboard</p>

Пример 2. Передача параметров через компактный массив и extract

Универсальная функция для рендеринга шаблонов.

Пример
// render.php
function render(string $template, array $variables): void {
    extract($variables, EXTR_OVERWRITE);
    if (file_exists(__DIR__ . '/templates/' . $template . '.php')) {
        include __DIR__ . '/templates/' . $template . '.php';
    } else {
        echo "Template not found.";
    }
}

// Использование
render('profile', [
    'username' => 'admin',
    'email' => 'admin@example.com',
    'avatar' => '/img/default.png'
]);

Шаблон templates/profile.php:

Пример
<div class="profile">
    <img src="<?= $avatar ?>">
    <h2><?= $username ?></h2>
    <p>Email: <?= $email ?></p>
</div>

Результат:

<div class="profile">
    <img src="/img/default.png">
    <h2>admin</h2>
    <p>Email: admin@example.com</p>
</div>

Пример 3. Использование include с условной загрузкой на основе нескольких GET-параметров

Подключение двух разных файлов в зависимости от комбинации параметров.

Пример
$lang = $_GET['lang'] ?? 'ru';
$theme = $_GET['theme'] ?? 'light';

if ($lang === 'en') {
    include "lang/en.php";
} else {
    include "lang/ru.php";
}

if ($theme === 'dark') {
    include "themes/dark.css.php";
} else {
    include "themes/light.css.php";
}

В каждом подключаемом файле можно использовать глобальные переменные, заданные ранее, например, $lang.

Пример 4. Безопасная замена ненадёжным включениям: file_get_contents + str_replace

Если необходимо загрузить внешнее содержимое с параметрами, можно использовать file_get_contents (если разрешено) и вывести результат, избегая eval.

Пример
$url = 'https://api.example.com/data?user=' . urlencode($_GET['user']);
$data = @file_get_contents($url);
if ($data !== false) {
    echo $data;
} else {
    echo 'Ошибка получения данных';
}

Внимание: это не include, а чтение удалённого ресурса. Полученный HTML не выполняется как PHP, а только выводится.

// Пример вывода при ?user=john
{"name":"John","age":30}

Пример 5. Исправление распространённой ошибки: include с параметром в пути

Демонстрация неверного подхода и его корректный аналог.

Пример
// Ошибочный код
include 'template.php?id=123'; // Warning: include(template.php?id=123)

// Правильный код
$id = 123;
include 'template.php'; // внутри template.php используем $id

Если очень нужно передать именно через GET (например, для совместимости со старым кодом), применяют временную установку $_GET:

Пример
$old_get = $_GET;
$_GET['id'] = 123;
include 'template.php';
$_GET = $old_get;

Важно восстановить исходный массив после использования.

Использование include с GET параметрами - comments

En
Php include get (php)