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

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

Функция pg_escape_string экранирует специальные символы в строке для безопасного использования в SQL-запросах к PostgreSQL. Её применяют при ручном формировании SQL-запросов для предотвращения инъекций. В современных приложениях предпочтительнее использовать подготовленные выражения.

Аргументы функции

Функция принимает два параметра:

  • $connection (обязательный с PHP 8.0) – ресурс соединения с PostgreSQL.
  • $data (обязательный) – строка, которую требуется экранировать.

До версии PHP 8.0 первый параметр был опционален. При его отсутствии использовалось последнее открытое соединение.

Базовые примеры
Экранирование строки
$conn = pg_connect("host=localhost dbname=test");
$input = "O'Reilly";
$escaped = pg_escape_string($conn, $input);
echo "INSERT INTO authors (name) VALUES ('" . $escaped . "')";
INSERT INTO authors (name) VALUES ('O''Reilly')
Экранирование строки с обратным слешем
$conn = pg_connect("host=localhost dbname=test");
$input = "Путь: C:\\files\\new";
$escaped = pg_escape_string($conn, $input);
echo "UPDATE log SET path = '" . $escaped . "'";
UPDATE log SET path = 'Путь: C:\\\\files\\\\new'
Альтернативы в PHP

Функция pg_escape_literal возвращает строку в кавычках, готовую для подстановки в запрос. Она автоматически добавляет кавычки.

$escaped = pg_escape_literal($conn, "O'Reilly");
echo "INSERT INTO authors (name) VALUES (" . $escaped . ")";
INSERT INTO authors (name) VALUES ('O''Reilly')
Подготовленные выражения (pg_prepare, pg_execute)

Наиболее безопасный способ. Параметры передаются отдельно от запроса, что исключает инъекции.

$result = pg_prepare($conn, "query", "INSERT INTO authors (name) VALUES ($1)");
$result = pg_execute($conn, "query", array("O'Reilly"));
Запрос выполняется без ошибок
Аналоги в других языках
Python (psycopg2)
import psycopg2
conn = psycopg2.connect("dbname=test")
cursor = conn.cursor()
cursor.execute("INSERT INTO authors (name) VALUES (%s)", ("O'Reilly",))

Библиотека использует параметризованные запросы, аналогичные подготовленным выражениям.

JavaScript (node-postgres)
const query = {
  text: 'INSERT INTO authors (name) VALUES ($1)',
  values: ["O'Reilly"]
};
client.query(query);

Передача параметров отдельно от текста запроса.

MySQL (PHP mysqli_real_escape_string)
$escaped = mysqli_real_escape_string($link, "O'Reilly");

Аналогичная функция для СУБД MySQL. Принцип работы схож, но экранируются разные символы.

Распространённые ошибки
Использование без соединения (PHP 8)
$input = "test'";
$escaped = pg_escape_string($input);
Fatal error: Uncaught ArgumentCountError: pg_escape_string() expects exactly 2 arguments, 1 given
Попытка экранирования массивов или объектов
$conn = pg_connect("host=localhost dbname=test");
$data = array('key' => 'value');
$escaped = pg_escape_string($conn, $data);
Warning: pg_escape_string() expects parameter 2 to be string, array given
Двойное экранирование
$conn = pg_connect("host=localhost dbname=test");
$input = "O'Reilly";
$escaped = pg_escape_string($conn, $input);
$doubleEscaped = pg_escape_string($conn, $escaped);
// В базе окажется значение O''Reilly вместо O'Reilly

Это приводит к сохранению лишних экранирующих символов.

Изменения в PHP 8

В PHP 8.0 параметр соединения стал обязательным. Ранее функция могла использовать последнее открытое соединение по умолчанию, что иногда приводило к ошибкам.

До PHP 8.0
$escaped = pg_escape_string("O'Reilly"); // Работало, если соединение было открыто
После PHP 8.0
$conn = pg_connect("...");
$escaped = pg_escape_string($conn, "O'Reilly"); // Соединение обязательно
Расширенные примеры
Экранирование данных JSON перед вставкой
Пример php
$conn = pg_connect("host=localhost dbname=test");
$jsonData = json_encode(['name' => "O'Connor", 'age' => 30]);
$escapedJson = pg_escape_string($conn, $jsonData);
$query = "INSERT INTO data (json_field) VALUES ('" . $escapedJson . "')";
echo $query;
INSERT INTO data (json_field) VALUES ('{"name":"O'Connor","age":30}')
Работа с разными кодировками

Функция корректно обрабатывает строки в кодировке соединения. Важно установить правильную кодировку при подключении.

Пример php
$conn = pg_connect("host=localhost dbname=test options='--client_encoding=UTF8'");
$input = "Текст с 'апострофом' и кириллицей";
$escaped = pg_escape_string($conn, $input);
echo "INSERT INTO test (text) VALUES ('" . $escaped . "')";
INSERT INTO test (text) VALUES ('Текст с ''апострофом'' и кириллицей')
Экранирование в условиях LIKE

Для оператора LIKE необходимо экранировать также символы % и _.

Пример php
$conn = pg_connect("host=localhost dbname=test");
$search = "100%_test";
$escapedLike = str_replace(['%', '_'], ['%', '_'], $search);
$escaped = pg_escape_string($conn, $escapedLike);
$query = "SELECT * FROM products WHERE name LIKE '%" . $escaped . "%' ESCAPE ''";
echo $query;
SELECT * FROM products WHERE name LIKE '%100%_test%' ESCAPE ''

PHP pg_escape_string function comments

En
Pg escape string Escape a string for query