Pg lo open: примеры (PHP)
pg_lo_open(PgSql\Connection $connection, int $oid, string $mode): PgSql\Lob|falseОписание функции pg_lo_open
Функция pg_lo_open в PHP открывает существующий большой объект (Large Object, LOB) в базе данных PostgreSQL для чтения или записи. Она является частью модуля PostgreSQL, предоставляющего низкоуровневый API для работы с данными, которые неудобно хранить в полях обычных таблиц (например, изображения, документы, аудиофайлы).
Функция применяется, когда требуется потоковое чтение или запись данных большого объекта. Это необходимо для обработки файлов, не загружая их целиком в оперативную память скрипта.
Функция имеет два варианта сигнатуры:
- pg_lo_open($connection, $oid, $mode) — устаревшая форма (не рекомендуется с PHP 7.4).
- pg_lo_open($connection, $oid, $mode) — предпочтительная форма с явным указанием соединения.
Параметры:
- $connection (ресурс соединения PgSql\Connection) — обязательный параметр, представляющий соединение с сервером PostgreSQL, полученное через
pg_connect(). - $oid (int) — обязательный идентификатор большого объекта (OID), который необходимо открыть. OID обычно получают через
pg_lo_create()илиpg_lo_import(). - $mode (string) — обязательная строка, определяющая режим доступа. Возможные значения:
"r"(только чтение),"w"(только запись),"rw"(чтение и запись).
Возвращаемое значение: в случае успеха функция возвращает ресурс большого объекта (ресурс (resource) или объект PgSql\Lob в PHP 8), либо false в случае ошибки.
Короткие примеры использования
<?php
$conn = pg_connect("dbname=test user=postgres");
$oid = 12345; // Допустим, это OID существующего объекта
$descriptor = pg_lo_open($conn, $oid, "r");
if ($descriptor) {
echo "Объект открыт для чтения.";
} else {
echo "Ошибка открытия объекта.";
}
?>Объект открыт для чтения.
<?php
$conn = pg_connect("dbname=test user=postgres");
$oid = pg_lo_create($conn); // Создаем новый объект и получаем его OID
$descriptor = pg_lo_open($conn, $oid, "w");
if ($descriptor) {
$data = "Данные для записи";
pg_lo_write($descriptor, $data);
pg_lo_close($descriptor);
echo "Запись завершена. OID: " . $oid;
}
?>Запись завершена. OID: 12346
<?php
$conn = pg_connect("dbname=test user=postgres");
$descriptor = pg_lo_open($conn, 999999, "r"); // Неверный OID
var_dump($descriptor);
?>bool(false)
Похожие функции в PHP
Создает большой объект из файла в локальной файловой системе. Функция полезна для быстрого импорта готовых файлов без ручного открытия и записи.
Сохраняет большой объект в файл. Альтернатива ручному чтению через pg_lo_open и pg_lo_read.
Считывает весь большой объект и сразу отправляет его непосредственно в браузер или другой вывод. Удобно для отдачи файлов, но не подходит для обработки данных в памяти.
pg_lo_open предпочтительнее, когда требуется потоковая обработка (по частям) или необходимо записывать данные порциями. pg_lo_import/pg_lo_export подходят для простого импорта/экспорта целиком. pg_lo_read_all используется для прямой отправки файла клиенту.
Аналоги в других языках и СУБД
Работа через методы lo_open(), lo_read(), lo_write() объекта Large Object. Отличие: более объектно-ориентированный интерфейс.
import psycopg2
conn = psycopg2.connect("dbname=test")
conn.autocommit = True
lob = conn.lobject(oid=12345, mode='r')
data = lob.read(100)
print(data)
lob.close()b'Содержимое объекта...'
Прямого аналога низкоуровневого API может не быть. Часто большие объекты обрабатываются через чтение полей типа BYTEA или через потоковые интерфейсы.
// Пример работы с BYTEA (не точный аналог)
const result = await pool.query('SELECT blob_data FROM files WHERE id=$1', [1]);
const buffer = result.rows[0].blob_data; // Данные уже в памятиPg lo open в MySQL
В MySQL нет точного аналога больших объектов PostgreSQL. Для хранения бинарных данных используются типы BLOB, а доступ к ним происходит через стандартные запросы SELECT/UPDATE, что может быть менее эффективно для очень больших файлов.
-- Чтение BLOB
SELECT file_data FROM blobs WHERE id = 1;Типичные ошибки
Попытка открыть объект по несуществующему или некорректному идентификатору.
<?php
$conn = pg_connect("dbname=test");
$descriptor = pg_lo_open($conn, 'invalid_oid', "r"); // OID должен быть integer
var_dump($descriptor);
?>bool(false)
Операции с большими объектами в PostgreSQL должны выполняться внутри транзакции. При использовании pg_lo_open с режимом записи вне транзакции может возникнуть ошибка.
<?php
$conn = pg_connect("dbname=test");
// pg_query($conn, "BEGIN"); // Транзакция не начата
$oid = pg_lo_create($conn);
$descriptor = pg_lo_open($conn, $oid, "w"); // Может не сработать
?>Указание недопустимой строки режима.
<?php
$conn = pg_connect("dbname=test");
$oid = 12345;
$descriptor = pg_lo_open($conn, $oid, "x"); // Недопустимый режим 'x'
var_dump($descriptor);
?>bool(false)
Изменения в последних версиях PHP
Функция pg_lo_open() теперь возвращает экземпляр класса PgSql\Lob вместо ресурса (resource). Тип возвращаемого значения указан как PgSql\Lob|false. Это часть общей тенденции замены ресурсов на объекты.
Объявлена устаревшей сигнатура функции без явного указания соединения в качестве первого аргумента. Рекомендуется всегда использовать форму с указанием соединения.
Расширенные примеры использования
<?php
$conn = pg_connect("dbname=test");
pg_query($conn, "BEGIN");
$oid = 12345; // OID объекта с текстом
$descriptor = pg_lo_open($conn, $oid, "r");
if ($descriptor) {
$buffer = '';
while (($chunk = pg_lo_read($descriptor, 4096)) !== false) {
$buffer .= $chunk;
// Обрабатываем буфер, находя строки
$lines = explode("\n", $buffer);
$buffer = array_pop($lines); // Последний фрагмент, возможно, неполная строка
foreach ($lines as $line) {
echo "Строка: $line<br>";
}
}
if (!empty($buffer)) {
echo "Последняя строка: $buffer<br>";
}
pg_lo_close($descriptor);
}
pg_query($conn, "COMMIT");
?><?php
$conn = pg_connect("dbname=test");
pg_query($conn, "BEGIN");
$oid = pg_lo_create($conn);
$descriptor = pg_lo_open($conn, $oid, "w");
if ($descriptor) {
$input = fopen('php://input', 'rb');
while (!feof($input)) {
$chunk = fread($input, 8192);
pg_lo_write($descriptor, $chunk);
}
fclose($input);
pg_lo_close($descriptor);
echo "Файл загружен в объект с OID: $oid";
}
pg_query($conn, "COMMIT");
?><?php
function copy_lob($conn, $src_oid, $dst_oid, $block_size = 2048) {
pg_query($conn, "BEGIN");
$src = pg_lo_open($conn, $src_oid, "r");
$dst = pg_lo_open($conn, $dst_oid, "w");
if (!$src || !$dst) {
return false;
}
$total = 0;
while (($data = pg_lo_read($src, $block_size)) !== false && strlen($data) > 0) {
pg_lo_write($dst, $data);
$total += strlen($data);
}
pg_lo_close($src);
pg_lo_close($dst);
pg_query($conn, "COMMIT");
return $total;
}
$conn = pg_connect("dbname=test");
$bytes = copy_lob($conn, 12345, 12346, 8192);
echo "Скопировано $bytes байт.";
?>Скопировано 1048576 байт.