Как получить ID из адресной строки в PHP

Раздел: Файловая система и ввод-вывод -> Файловая система и подключение файлов

При разработке веб-приложений часто требуется извлечь идентификатор (ID) из URI (Uniform Resource Identifier) для загрузки соответствующего файла, записи из базы данных или маршрутизации. В разделе Файловая система и подключение файлов это может быть необходимо для подключения файла, имя которого содержит ID (например, include 'theme_' . $id . '.php'). Ниже рассмотрены различные подходы к получению ID из URI в PHP.

Основной метод: разбор URI с помощью parse_url и регулярного выражения

Наиболее универсальное решение заключается в комбинации функций parse_url() и preg_match(). Сначала извлекается компонент пути, затем с помощью регулярного выражения находится числовой идентификатор.


$uri = $_SERVER['REQUEST_URI'];
$parsed = parse_url($uri);
$path = $parsed['path'] ?? '';
if (preg_match('/\d+/', $path, $matches)) {
    $id = (int) $matches[0];
} else {
    $id = null;
}
  

Пояснение: $_SERVER['REQUEST_URI'] возвращает полный URI текущего запроса. parse_url() разбивает его на компоненты, среди которых нас интересует path. Регулярное выражение /\d+/ находит первое вхождение одной или нескольких цифр. Преобразование в целое число с помощью (int) повышает безопасность.

Типичные проблемы: Если в URI присутствует несколько чисел (например, /user/5/post/10), будет найдено только первое. Необходимо проверять, что $id не равен null, прежде чем использовать его в файловых операциях, чтобы избежать ошибки подключения несуществующего файла. Также следует фильтровать ID (например, preg_replace('/[^0-9]/', '', $id)) для предотвращения path traversal.

Как извлечь ID из URL вида /page/123, если ID всегда последний сегмент?

Вариант с explode и end

Для простых URI, где ID находится в последней части пути, подойдёт разбиение строки с помощью explode() и получение последнего элемента через end().


$uri = '/articles/42';
$parts = explode('/', trim($uri, '/'));
$last = end($parts);
$id = ctype_digit($last) ? (int)$last : null;
  

Пояснение: trim($uri, '/') удаляет начальные и конечные слеши. explode создаёт массив сегментов. end() возвращает последний элемент. Проверка ctype_digit() гарантирует, что это цифры. Если URI содержит параметры запроса (/page/123?q=test), explode включит 123?q=test – нужно предварительно отбросить query с помощью strtok($uri, '?').

Ошибки: Забывают удалить query-строку, что приводит к некорректному результату. Также если в URI есть дополнительные сегменты после ID, метод не сработает.

Как получить ID, если он является последней частью URI (например, /file/123)?

Вариант с basename

Функция basename() возвращает последний компонент пути, игнорируя слеши. Это удобно, когда URI заканчивается на /123.


$uri = '/download/789';
$id = basename($uri);
if (ctype_digit($id)) {
    $id = (int)$id;
} else {
    $id = null;
}
  

Пояснение: basename() работает как с реальными путями, так и с URI. Однако если в URI присутствует query-строка, basename также включит её (например, 789?token=abc). Необходимо предварительно удалить параметры.

Недостатки: Нет возможности извлечь ID из середины URI. После basename требуется дополнительная проверка, чтобы убедиться, что результат является числом.

Как получить ID из чистого URL без параметров запроса (при включённом mod_rewrite)?

Использование $_SERVER['PATH_INFO']

Если сервер сконфигурирован с mod_rewrite или CGI, переменная $_SERVER['PATH_INFO'] содержит дополнительный путь после имени скрипта (например, /index.php/123/123).


$pathInfo = $_SERVER['PATH_INFO'] ?? '';
$id = trim($pathInfo, '/');
$id = ctype_digit($id) ? (int)$id : null;
  

Пояснение: $pathInfo берётся из серверной переменной, которая часто содержит чистый ID. Этот метод подходит только для определённых конфигураций веб-сервера.

Проблема: $_SERVER['PATH_INFO'] может отсутствовать, если не используется URL rewriting или если запрос обрабатывается напрямую. Также требуется проверка на наличие нескольких сегментов.

Как извлечь ID из URI с фиксированным шаблоном, например /category/5/item/42?

Регулярное выражение с именованными группами

Для сложных шаблонов URI удобно использовать preg_match() с именованными захватами. Это повышает читаемость и упрощает поддержку.


$uri = '/category/12/item/34';
$pattern = '#/category/(?P<cat_id>\d+)/item/(?P<item_id>\d+)#';
if (preg_match($pattern, $uri, $matches)) {
    $catId = (int)$matches['cat_id'];
    $itemId = (int)$matches['item_id'];
}
  

Пояснение: Шаблон содержит именованные группы cat_id и item_id. После совпадения в $matches появляются ассоциативные ключи. Этот подход легко расширяется для других шаблонов.

Ошибки: Неправильное экранирование слешей в шаблоне (нужно использовать другой разделитель, например #, чтобы избежать \/). Также важно проверять успешность совпадения.

Как получить ID, переданный через query string, например ?id=123?

Использование $_GET или filter_input

Самый простой способ – обратиться к суперглобальному массиву $_GET или использовать filter_input() с валидацией.


$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    $id = 0; // значение по умолчанию
}
  

Пояснение: filter_input() не только получает параметр, но и проверяет его на соответствие целому числу. Это защищает от внедрения строковых атак. Альтернатива: $_GET['id'] (с проверкой isset и ctype_digit).

Недостатки: Зависит от метода запроса (GET). Параметр может быть изменён пользователем. Всегда требуется фильтрация, особенно перед подключением файла (например, include "templates/{$id}.php" – возможна подстановка пути).

Далее представлены расширенные примеры извлечения ID из URI с различными сценариями и подробными результатами.

Пример 1: Извлечение всех числовых ID из URI с query-строкой

Пример

$uri = '/products/12/reviews/34?sort=asc';
$parsed = parse_url($uri);
$path = $parsed['path'] ?? '';
preg_match_all('/\d+/', $path, $matches);
$ids = $matches[0];
var_dump($ids);
array(2) {
  [0] =>
  string(2) "12"
  [1] =>
  string(2) "34"
}

Пояснение: preg_match_all() находит все цифровые последовательности в пути. Результат содержит массив строк, которые можно преобразовать в целые числа.

Пример 2: Извлечение ID из имени файла с расширением

Пример

$uri = '/uploads/images/photo_123.jpg';
$basename = basename($uri, '.jpg'); // 'photo_123'
preg_match('/\d+/', $basename, $match);
$id = $match[0] ?? null;
var_dump($id);
string(3) "123"

Пояснение: basename() со вторым аргументом отсекает расширение. Регулярное выражение извлекает число из оставшейся части. Если расширение неизвестно, можно обойтись pathinfo().

Пример 3: Безопасное извлечение ID с привязкой к шаблону

Пример

$uri = '/user/42';
$id = null;
if (preg_match('#/user/(\d+)#', $uri, $matches)) {
    $id = (int) $matches[1];
}
var_dump($id);
int(42)

Пояснение: Шаблон #/user/(\d+)# требует, чтобы URI содержал /user/ перед числом. Это исключает ложные срабатывания на других частях URI.

Пример 4: Получение ID из GET-параметра с фильтрацией и значением по умолчанию

Пример

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    $id = 0;
}
var_dump($id);
int(42)  // при ?id=42

Пояснение: filter_input возвращает false для невалидного целого и null при отсутствии параметра. Присваивание 0 в качестве значения по умолчанию предотвращает ошибки.

Пример 5: Извлечение нескольких ID из сегментов URI

Пример

$uri = '/compare/100/200/300';
$ids = array_filter(explode('/', trim($uri, '/')), 'is_numeric');
$ids = array_values($ids);
print_r($ids);
Array
(
    [0] => 100
    [1] => 200
    [2] => 300
)

Пояснение: explode разбивает путь, array_filter с callback is_numeric отбрасывает нечисловые сегменты. array_values переиндексирует массив.

Пример 6: Извлечение ID из query-строки с помощью parse_str

Пример

$uri = '/page?item_id=123&action=view';
$parsed = parse_url($uri);
parse_str($parsed['query'] ?? '', $params);
$item_id = $params['item_id'] ?? null;
var_dump($item_id);
string(3) "123"

Пояснение: parse_str() преобразует query-строку в ассоциативный массив. Метод полезен, когда нужно извлечь параметры из URI, не являющегося текущим запросом.

Пример 7: Извлечение последнего числового сегмента с помощью array_reverse

Пример

$uri = '/products/456/';
$parts = explode('/', trim($uri, '/'));
$reversed = array_reverse($parts);
foreach ($reversed as $part) {
    if (ctype_digit($part)) {
        $id = (int) $part;
        break;
    }
}
var_dump($id ?? null);
int(456)

Пояснение: array_reverse позволяет найти последнее число в пути, даже если перед ID есть другие нечисловые сегменты. Цикл прерывается на первом найденном числе.

Получить URI с ID в PHP - comments

En
Uri php id (php)