Большие объекты

Иногда для работы приложения требуется хранить «большие» порции данных в базе. Часто под большим понимают объем данных «около 4 килобайтов или больше», хотя отдельные базы данных спокойно обрабатывают до 32 килобайтов, прежде чем размер данных становится «большим». Большие объекты (англ. Large Objects, LOB) бывают текстовыми или двоичными. Модуль PDO разрешает работать с такими объектами путём установки типа данных PDO::PARAM_LOB в методах PDOStatement::bindParam() или PDOStatement::bindColumn(). Флаг PDO::PARAM_LOB сообщает объекту PDO, что данные требуется отобразить в виде потока, чтобы управлять данными через API-интерфейс PHP-потоков.

Пример #1 Вывод изображения, которое хранится в базе данных

В примере LOB-объект связывают с переменной $lob, а затем отправляют в браузер функцией fpassthru(). Поскольку PDO-объект представил LOB-объект как поток, с большим объектом получится работать функциями наподобие fgets(), fread() и stream_get_contents().

<?php

$db
= new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');

$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);

header("Content-Type: $type");

fpassthru($lob);

?>

Пример #2 Вставка изображения в базу данных

Следующий пример открывает файл и передаёт дескриптор файла в объект PDO для вставки файла в базу данных в виде LOB-объекта. Объект PDO извлечёт содержимое файла и вставит его в базу данных самым эффективным способом.

<?php

$db
= new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');

$stmt = $db->prepare("insert into images (id, contenttype, imagedata) values (?, ?, ?)");
$id = get_new_id(); // Некоторая функция, которая выделит новый ID

// Предположим, что находимся на странице загрузки файлов на удалённый сервер

$fp = fopen($_FILES['file']['tmp_name'], 'rb');

$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);

$db->beginTransaction();
$stmt->execute();
$db->commit();

?>

Пример #3 Вставка изображения в базу данных: Oracle

БД Oracle требует другой синтаксис для извлечения содержимого файла в виде LOB-объекта и вставки большого объекта в базу данных. Вставку больших объектов в БД выполняют в рамках транзакции, иначе БД зафиксирует LOB-объект, который только что вставила, с нулевой длиной — как часть неявной фиксации, которая возникает при выполнении каждого запроса.

<?php

$db
= new PDO('oci:', 'scott', 'tiger');

$stmt = $db->prepare("insert into images (id, contenttype, imagedata) " .
"VALUES (?, ?, EMPTY_BLOB()) RETURNING imagedata INTO ?")
;

$id = get_new_id(); // Некоторая функция, которая выделит новый ID

// Предположим, что находимся на странице загрузки файлов на удалённый сервер

$fp = fopen($_FILES['file']['tmp_name'], 'rb');

$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);

$db->beginTransaction();
$stmt->execute();
$db->commit();

?>