Pg escape literal: примеры (PHP)

Функция pg_escape_literal в PHP: полный обзор с примерами
Раздел: Базы данных (PostgreSQL)
pg_escape_literal(PgSql\Connection $connection, string $data): string

Функция pg_escape_literal в PHP предназначена для экранирования строковых литералов при работе с базой данных PostgreSQL. Её основная задача — корректно обработать строки, которые будут использоваться в SQL-запросах, чтобы предотвратить SQL-инъекции и обеспечить правильную интерпретацию специальных символов.

Назначение и применение

Использование функции актуально при формировании SQL-запросов путем конкатенации строк, когда применение подготовленных выражений с параметрами по каким-либо причинам невозможно. Функция добавляет необходимые кавычки вокруг экранированной строки.

Аргументы функции
  • connection (необязательный): Ресурс подключения к PostgreSQL. Начиная с PHP 8.1, этот аргумент может быть опущен. В этом случае используется последнее соединение, созданное функцией pg_connect().
  • data (обязательный): Строка (string), которую требуется экранировать и заключить в кавычки.

Возвращаемое значение: строка, содержащая экранированные данные, заключенные в одинарные кавычки, или FALSE в случае ошибки.

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

Пример с явным указанием подключения:

<?
$conn = pg_connect('dbname=test');
$string = "O'Reilly";
$escaped = pg_escape_literal($conn, $string);
echo $escaped;
?>
'O''Reilly'

Пример с использованием подключения по умолчанию (PHP >= 8.1):

<?
$conn = pg_connect('dbname=test'); // Становится подключением по умолчанию
$value = "Спец\nсимволы";
$result = pg_escape_literal($value);
echo $result;
?>
'Спец\nсимволы'

Обработка пустой строки и значения NULL:

<?
$escapedEmpty = pg_escape_literal($conn, '');
$escapedNull = pg_escape_literal($conn, null);
echo $escapedEmpty . '\n';
echo $escapedNull;
?>
''
'NULL'
Похожие функции в PHP
  • pg_escape_string(): Экранирует строку, но не добавляет обрамляющие кавычки. Требует самостоятельного добавления кавычек в запрос. Часто используется с двоичными данными.
  • pg_escape_identifier(): Предназначена для экранирования идентификаторов (например, имен таблиц, столбцов). Заключает результат в двойные кавычки.
  • Подготовленные выражения (pg_prepare/pg_execute): Наиболее предпочтительный и безопасный метод. Параметры передаются отдельно от текста запроса, что полностью исключает риск инъекций. Используется в большинстве случаев вместо функций экранирования.
  • pg_query_params(): Выполняет параметризованный запрос без этапа явной подготовки, что также является безопасной альтернативой.

Функции экранирования стоит применять только в случаях динамического формирования сложных частей запроса, например, имен таблиц, или при невозможности использования параметризованных запросов.

Аналоги в других языках и СУБД
Python (psycopg2)

Используются параметризованные запросы или метод mogrify().

import psycopg2
conn = psycopg2.connect('dbname=test')
cursor = conn.cursor()
safe_sql = cursor.mogrify('SELECT * FROM t WHERE col = %s', ["O'Reilly"])
print(safe_sql.decode())
SELECT * FROM t WHERE col = 'O''Reilly'
JavaScript (Node.js, библиотека pg)

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

const { Client } = require('pg');
const client = new Client();
const query = {
  text: 'SELECT * FROM users WHERE name = $1',
  values: ["O'Reilly"]
};
// Значение из values будет автоматически экранировано
MySQL (PHP, функция mysqli_real_escape_string)

Аналог pg_escape_string, а не pg_escape_literal. Не добавляет кавычки.

<?
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$escaped = $mysqli->real_escape_string("O'Reilly");
echo "'$escaped'"; // Кавычки добавляются вручную
?>
'O\'Reilly'
Типичные ошибки
Отсутствие подключения в PHP < 8.1

Вызов без аргумента подключения в версиях до PHP 8.1 приводит к предупреждению.

<?
// PHP 8.0 или ниже
$escaped = pg_escape_literal("test"); // Нет подключения
?>
Warning: pg_escape_literal() expects exactly 2 arguments, 1 given
Экранирование уже экранированных данных

Приводит к двойному экранированию и искажению данных.

<?
$conn = pg_connect('dbname=test');
$input = "O'Reilly";
$once = pg_escape_literal($conn, $input); // 'O''Reilly'
$twice = pg_escape_literal($conn, $once); // Ошибка
?>

Строка $twice будет содержать лишние экранирующие символы.

Использование для нестроковых значений

Функция ожидает строку. Передача других типов (массивов, объектов) может привести к неожиданному результату.

<?
$escaped = pg_escape_literal($conn, true); // bool(true)
echo $escaped;
?>
'1'
История изменений
  • PHP 8.1.0: Аргумент connection стал необязательным. Если он не указан, используется подключение по умолчанию.
  • PHP 8.0.0: Тип возвращаемого значения в случае ошибки изменен с string|false на string. Теперь функция выбрасывает исключение ValueError, если не удалось получить строку для экранирования (например, передан неверный тип), и TypeError при неверном количестве аргументов. Ранее возвращалось FALSE.
Расширенные примеры
Динамическое формирование условия IN

Параметризованные запросы не поддерживают динамический список в IN. Можно использовать экранирование, но с осторожностью.

Пример php
<?
$conn = pg_connect('dbname=test');
$ids = [10, 20, 'foo'];
$escapedIds = array_map(fn($id) => pg_escape_literal($conn, $id), $ids);
$sql = 'SELECT * FROM items WHERE id IN (' . implode(', ', $escapedIds) . ')';
echo $sql;
?>
SELECT * FROM items WHERE id IN ('10', '20', 'foo')
Работа с многострочным текстом и спецсимволами
Пример php
<?
$text = "Первая строка\nВторая 'строка'\r\nСлэш: \\";
$escaped = pg_escape_literal($conn, $text);
echo $escaped . '\n';
// Использование в запросе
$query = 'INSERT INTO logs (message) VALUES (' . $escaped . ')';
echo $query;
?>
'Первая строка\nВторая ''строка''\r\nСлэш: \\'
INSERT INTO logs (message) VALUES ('Первая строка\nВторая ''строка''\r\nСлэш: \\')
Сравнение с ручным добавлением кавычек

Использование pg_escape_string требует ручного управления кавычками.

Пример php
<?
$unsafe = "O'Reilly";
$escaped1 = '\'' . pg_escape_string($conn, $unsafe) . '\'';
$escaped2 = pg_escape_literal($conn, $unsafe);
var_dump($escaped1 === $escaped2);
?>
bool(true)

PHP pg_escape_literal function comments

En
Pg escape literal Escape a literal for insertion into a text field