Обработка ID записей в PHP-скриптах: от простых решений к безопасным

Раздел: Программирование -> Работа с базой данных

Принципы обработки идентификатора записи в PHP

Как обеспечить безопасное получение ID из URL?

Наиболее эффективный способ - использование подготовленных запросов (prepared statements) с PDO. Это предотвращает SQL-инъекции и упрощает код. Пример проверки ID через filter_input и последующего запроса:


// Получение ID из GET-параметра с проверкой
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if ($id === false || $id === null) {
    // Обработка отсутствия или некорректного ID
    echo "ID не указан или не является числом.";
    exit;
}
// Подключение к БД (пример)
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->execute(['id' => $id]);
$article = $stmt->fetch();
if ($article) {
    echo "Запись найдена: " . htmlspecialchars($article['title']);
} else {
    echo "Запись с таким ID не существует.";
}
    

Типичные проблемы

  • Использование непроверенного $_GET['id'] в SQL запросе - уязвимость к инъекциям.
  • Отсутствие проверки на существование записи приводит к ошибкам или пустому выводу.
  • Неправильная обработка типов (строка вместо числа) может вызвать ошибку запроса.

Решение: всегда проверять ID, использовать подготовленные запросы и обрабатывать случай отсутствия записи.

Вариант 1: использование intval() для приведения к целому

Простой способ, если не требуется защита от инъекций (например, при работе с уже экранированными данными).


$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
$sql = "SELECT * FROM articles WHERE id = $id"; // всё равно опасно
    
Не защищает от SQL-инъекций, если значение используется в строке запроса без кавычек.

Вариант 2: mysqli с экранированием

Использование mysqli_real_escape_string и приведения к числу.


$id = intval($_GET['id'] ?? 0);
$mysqli = new mysqli(...);
$id = $mysqli->real_escape_string($id); // избыточно для integer
$result = $mysqli->query("SELECT * FROM articles WHERE id = $id");
    

Вариант 3: проверка с помощью регулярного выражения

Когда ID может быть не только числом, но и строкой определённого формата.


$id = $_GET['id'] ?? '';
if (preg_match('/^[1-9]\d*$/', $id)) {
    // безопасно использовать в запросе после экранирования
}
    

Расширенные примеры работы с ID

Пример с использованием named placeholders и обработкой ошибок PDO

Полный скрипт с проверкой существования записи и выводом.

Пример

<?php
try {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass', [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    ]);
    $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
    if ($id === false || $id === null) {
        throw new InvalidArgumentException('Некорректный ID');
    }
    $stmt = $pdo->prepare('SELECT title, content FROM articles WHERE id = :id');
    $stmt->execute(['id' => $id]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$row) {
        throw new Exception('Запись не найдена');
    }
    echo '<h1>' . htmlspecialchars($row['title']) . '</h1>';
    echo '<p>' . nl2br(htmlspecialchars($row['content'])) . '</p>';
} catch (Exception $e) {
    echo 'Ошибка: ' . $e->getMessage();
}
?>
Вывод: заголовок и содержимое статьи, если ID корректен и запись существует, иначе сообщение об ошибке.

Пример с передачей массива ID (IN конструкция)

Как получить несколько записей по списку ID из URL (id=1,2,3).

Пример

$ids = $_GET['id'] ?? '';
$idsArray = array_map('intval', explode(',', $ids));
$placeholders = implode(',', array_fill(0, count($idsArray), '?'));
$stmt = $pdo->prepare("SELECT * FROM articles WHERE id IN ($placeholders)");
$stmt->execute($idsArray);
$articles = $stmt->fetchAll();
Массив записей, соответствующих перечисленным ID.

Пример использования фильтрации с FILTER_VALIDATE_INT и опциями

Ограничение диапазона ID от 1 до 1000.

Пример

$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 1000]
]);
if ($id) { 
    // безопасное использование
}
Переменная $id содержит целое число в заданном диапазоне или false/null при несоответствии.

Работа с ID записей - comments

En
Index php id 5 (php)