Большие объекты (LOB)
Иногда для работы приложения необходимо хранить "большие" порции данных в базе.
Обычно, под большим понимают объем данных "около 4 килобайт или больше", хотя
некоторые базы данных могут спокойно обрабатывать до 32 килобайт, прежде чем
размер данных становится "большим". Большие объекты могут быть текстовыми или
двоичными. PDO позволяет работать с такими объектами путем установки типа данных
PDO::PARAM_LOB
в методах
PDOStatement::bindParam() или
PDOStatement::bindColumn().
PDO::PARAM_LOB
сообщает PDO, что нужно пометить эти данные,
как поток. И соответственно работать с такими объектами можно, используя
API потоков PHP.
Пример #1 Вывод изображения, хранящегося в базе данных
В этом примере переменной $lob задают в соответствие большой объект LOB, а затем отсылают ее в браузер с помощью функции fpassthru(). Так как 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 будет зафиксирован в базе с нулевой длиной, так как если не обозначить границы транзакции, изменения будут фиксироваться после каждого выполненного запроса.
<?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();
?>