PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 150 · После BSON-значений и чтения MongoDB через драйвер
MongoDB: BSON Document — поля, копия, файл и Extended JSON
Читать необязательные поля, исправлять отдельную копию, сохранять BSON-типы и получать из базы только нужную карточку.
Зачем документу отдельный тип
Сервис получил заказ: город доставки, позиции, необязательная страховка и цена. Нужно прочитать именно нужные поля, сохранить их типы при передаче и подготовить исправленную копию, не затронув исходник. BSON Document решает задачу представления одного документа; это ещё не коллекция и не запрос к MongoDB.
| Задача | Вход | Видимый результат |
|---|---|---|
| Снимок доставки | Тула в PHP-массиве | Document сохраняет Тулу после изменения исходного массива |
| Необязательная доплата | missing / null / 0 | Три разных состояния, без потери нуля |
| Исправление адреса | Тула, Мира, 5 | Новая копия Казань, Баумана, 8; исходник сохранён |
| Обмен типизированным счётчиком | Int64("7") | Canonical сохраняет тип, Relaxed может его сузить |
| Карточка товара | Два товара на сервере | Один Document только с нужными полями |
- PHP-массив: order=ORD-119
- Document::fromPHP
- BSON Document с именами полей
- get("delivery") → вложенный Document
- get("city") → строка Тула
- toPHP → отдельная редактируемая копия
Представьте подписанный бланк заказа: у каждого поля своё имя и тип значения. Document хранит готовое BSON-представление, которое читают по именам, но не исправляют на месте. Это только модель: в памяти не бумажный бланк, а бинарные BSON-данные; неизменяемость этого объекта не означает блокировку записи в базе или транзакционный snapshot.
Первое действие: создать значение и прочитать город
$document = MongoDB\BSON\Document::fromPHP(['city' => 'Тула']);
$city = $document->get('city');
echo $city; // Тула$document — переменная; = сохраняет результат; ["city" => "Тула"] задаёт соответствие имени и значения. :: вызывает статическую фабрику класса, которая возвращает новый объект. ->get(...) читает поле созданного объекта. Точки с запятой завершают инструкции. Этот короткий механизм входит в полный снимок доставки ниже и не требует сервера.
Document имеет закрытый конструктор: прямой new Document() не используется. Фабрики fromPHP/fromJSON/fromBSON различаются входом, а возвращают один класс. Подробные основы: массивы, аргумент и возвращаемое значение, объект и метод. BSON-значения цены, даты и ID разобраны в предыдущей главе о типах.
Document, BSONDocument и обычный PHP-массив
Похожие названия относятся к разным слоям. Код из одного слоя нельзя механически переносить в другой: например, getArrayCopy у библиотечного BSONDocument не является методом Document расширения.
| Тип / слой | Для чего служит |
|---|---|
| MongoDB\BSON\Document | Неизменяемый BSON-документ расширения mongodb; 15 методов этой главы |
| MongoDB\BSON\PackedArray | BSON-список с последовательными позициями; соседняя глава |
| MongoDB\Model\BSONDocument | Класс библиотеки Composer, основан на ArrayObject; библиотека обычно возвращает его для документов |
| stdClass | Обычный PHP-объект с публичными свойствами; стандартная форма декодированного документа без специальных правил |
| PHP array | Массив PHP: способен представлять и список, и соответствие ключей значениям |
| MongoDB\Collection | Библиотечный интерфейс к коллекции на сервере; это не один документ |
| MongoDB\Driver\Cursor | Результат запроса, выдающий документы; итератор полей Document обходит только один документ |
Не требуется устанавливать Composer только ради Document. В программах используется расширение; библиотека упомянута для различения. Практика списков и BSON Iterator: PackedArray и обход вложенных значений.
Как запустить и увидеть результат
Первые шесть программ локально преобразуют данные средствами PHP/ext-mongodb; MongoDB-сервер не вызывается. Последняя projected-catalog выполняет настоящую запись и ограниченное чтение на локальном MongoDB 8.0. Во всех архивах нужны PHP 8.4+ CLI x64 и mongodb 2.5+; контрольная среда PHP 8.5.11, расширение 2.5.5, для серверной программы MongoDB 8.0.34.
В каждом ZIP находятся example.php, bd119-helper.php и README.txt. Распакуйте и выполните php example.php, затем откройте result.html. JSON содержит те же строки; metrics.json — версии, булевы проверки и хеши. У локальных кодеков runtime.server прямо говорит, что сервер не вызывался.
Для projected-catalog README содержит установку MongoDB/DLL, создание нового каталога, loopback-запуск на 27075 и PHPMAN_MONGODB_URI/PHPMAN_MONGODB_DATABASE. Программа создаёт случайное имя своей коллекции, отмечает владение после create, удаляет точное имя в finally и проверяет отсутствие. Чужая база, dropDatabase и изменения конфигурации не используются.
binary-archive создаёт собственный новый файл в режиме x+b, реально пишет и читает BSON, затем убирает этот файл. Для него нужны права записи в каталог распакованного примера. Открываемый на сайте HTML — сохранённый результат запуска, а не команда вашему MongoDB.
Собрать документ доставки и прочитать вложенные значения
Службе доставки нужен снимок заказа: город, способ выдачи и позиции. После создания такого значения исходная PHP-форма может измениться, но уже подготовленные данные доставки должны оставаться прежними.
Исходные данные
ORD-119: город Тула, самовывоз true, товары Кружка и Чай. instructions — пустой документ {}, labels — пустой список []. Затем в исходном PHP-массиве город меняется на Казань.
- PHP: order и delivery.city=Тула
- fromPHP создаёт BSON Document
- delivery читается как вложенный Document
- items читается как PackedArray
- Исходный PHP-массив меняется на Казань
- Document по-прежнему содержит Тулу
Короткое действие
$document = MongoDB\BSON\Document::fromPHP([
'order' => 'ORD-119',
'delivery' => ['city' => 'Тула'],
]);
$city = $document->get('delivery')->get('city'); // Тула
// fromPHP создаёт значение в PHP; в базу оно ещё не записано.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Что читаем | Результат |
|---|---|
| Номер заказа | ORD-119 |
| Город внутри документа | Тула |
| Город в изменённом PHP-массиве | Казань |
| Самовывоз | true |
| Первая позиция | Кружка |
| Пустые инструкции | BSON Document |
| Пустой список меток | BSON PackedArray |
| new Document() | Error: private constructor |
| Числовой ключ корневого документа | первый |
Разбор по шагам
Document — значение расширения MongoDB в памяти процесса. fromPHP — статическая фабрика: метод класса создаёт объект без прямого new Document(). Конструктор закрыт; намеренная попытка new в полном примере даёт Error и перехватывается.
get("order") читает поле по имени. Для вложенного документа сначала получаем get("delivery"), затем у него get("city"). Список items — PackedArray, его первая позиция имеет индекс 0. Здесь это две разные BSON-формы, хотя PHP умеет описывать обе своим типом array.
(object) [] явно создаёт пустой документ инструкций, а [] — пустой список меток. Если передать в fromPHP корневой список, он всё равно станет документом с ключами "0", "1": фабрика создаёт именно Document. Для отдельного списка есть PackedArray::fromPHP.
Изменение $input после fromPHP не правит созданное BSON-значение. Это полезно для подготовки сообщения/снимка, но ещё не означает сохранение на диск или отправку в MongoDB. В этом примере сервер не вызывается.
Ошибки и границы
Модель «подписанный снимок заказа» объясняет неизменяемость значения, но не является транзакционным snapshot базы. Document сам не проверяет обязательность города, допустимость товаров или права пользователя. Эти правила применяются до подготовки сообщения.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$input=['order'=>'ORD-119','delivery'=>['city'=>'Тула','pickup'=>true],
'items'=>['Кружка','Чай'],'instructions'=>(object)[],'labels'=>[]];
$document=Document::fromPHP($input);
$input['delivery']['city']='Казань';
$directError=false;try{new Document();}catch(Error $failure){$directError=true;}
$delivery=$document->get('delivery');$items=$document->get('items');
$instructions=$document->get('instructions');$labels=$document->get('labels');
$numeric=Document::fromPHP(['первый','второй']);
$rows=[
['Номер заказа',$document->get('order')],
['Город внутри документа',$delivery->get('city')],
['Город в изменённом PHP-массиве',$input['delivery']['city']],
['Самовывоз',bd119Display($delivery->get('pickup'))],
['Первая позиция',$items->get(0)],
['Пустые инструкции',bd119Display($instructions)],
['Пустой список меток',bd119Display($labels)],
['new Document()',$directError?'Error: private constructor':'неожиданный успех'],
['Числовой ключ корневого документа',$numeric->get('0')],
];
$checks=['root_document'=>$document instanceof Document,'nested_document'=>$delivery instanceof Document,
'nested_array'=>$items instanceof MongoDB\BSON\PackedArray,
'original_snapshot'=>$delivery->get('city')==='Тула' && $input['delivery']['city']==='Казань',
'empty_shape'=>$instructions instanceof Document && $labels instanceof MongoDB\BSON\PackedArray,
'private_constructor'=>$directError,'numeric_root_is_document'=>$numeric instanceof Document && $numeric->has('0')];
bd119Report('mongodb119-documents-delivery-snapshot', ['Что читаем', 'Результат'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-delivery-snapshot: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-delivery-snapshot: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Поменяйте город в $input ещё раз после fromPHP. В исходном Document должна остаться Тула. Для новой версии доставки создайте новый Document из нового массива; не пытайтесь изменить старый через [].
Отличить неуказанное поле, NULL и нулевую доплату
В заявке страховка может быть не передана, неизвестна или равна нулю. Если смешать эти случаи, интерфейс покажет неверную доплату либо сервер потеряет смысл входа.
Исходные данные
Три документа: без insurance, с insurance=null, с insurance=0. Отдельный документ содержит одновременно вложенное delivery.city и буквальное имя поля "delivery.city".
- has проверяет присутствие ключа
- offsetExists проверяет тот же факт
- Ключ есть → get или [] читает значение
- NULL не означает missing
- 0 не означает false результата поиска
- Для вложенности читаем по одному Document
Короткое действие
if ($document->has('insurance')) {
$insurance = $document->get('insurance'); // Может быть null или 0.
} else {
// Поле отсутствует: используйте отдельное правило приложения.
}
// get('delivery.city') ищет буквальное имя, не путь через вложенный Document.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Ситуация | has | offsetExists | get | Чтение [] / вложенного поля |
|---|---|---|---|---|
| Поле не передано | false | false | нет поля | не читаем |
| Явно неизвестно | true | true | NULL | NULL |
| Доплата ноль | true | true | 0 | 0 |
| Неверное чтение missing | RuntimeException | RuntimeException | get и offsetGet | нет значения |
| Ключ delivery.city | true | true | буквальное имя | Тула |
Разбор по шагам
has возвращает bool: true, когда ключ существует, в том числе при null и 0. offsetExists — соответствующий метод ArrayAccess. Он не является проверкой «значение не null», как isset у обычного PHP-массива; используйте понятный явный договор присутствия.
get и offsetGet возвращают значение, но для отсутствующего ключа выбрасывают RuntimeException. Поэтому перед необязательным чтением сначала проверяется наличие. Скобки $document["insurance"] используют offsetGet; чтение не делает Document изменяемым.
В подписи методов has/get ключ имеет тип string, у методов ArrayAccess — mixed. Это не приглашение передавать пользовательские массивы или объекты как имена: в прикладном коде выбирайте проверенную строку из разрешённого набора.
get("delivery.city") ищет буквальный ключ. Это не серверный путь projection/filter. Вложенный город читается через get("delivery")->get("city"). В таблице два способа намеренно дают разные значения.
Ошибки и границы
У договора интеграции должны быть отдельные значения для «не менять поле», «очистить поле» и «записать ноль», если такие операции нужны. Наличие BSON-поля не означает, что пользователь вправе его изменять. Точка в ключе здесь иллюстрирует локальный доступ; это не рекомендация проектировать рабочую схему с такими именами.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$documents=[
'Поле не передано'=>Document::fromPHP(['order'=>'A']),
'Явно неизвестно'=>Document::fromPHP(['order'=>'B','insurance'=>null]),
'Доплата ноль'=>Document::fromPHP(['order'=>'C','insurance'=>0]),
];
$rows=[];$states=[];
foreach($documents as $label=>$document){
$has=$document->has('insurance');$offset=$document->offsetExists('insurance');
$value=$has?bd119Display($document->get('insurance')):'нет поля';
$brackets=$offset?bd119Display($document['insurance']):'не читаем';
$rows[]=[$label,$has?'true':'false',$offset?'true':'false',$value,$brackets];
$states[]=[$has,$offset,$value,$brackets];
}
$missingGet=false;try{$documents['Поле не передано']->get('insurance');}
catch(MongoDB\Driver\Exception\RuntimeException $failure){$missingGet=true;}
$missingOffset=false;try{$documents['Поле не передано']->offsetGet('insurance');}
catch(MongoDB\Driver\Exception\RuntimeException $failure){$missingOffset=true;}
$literal=Document::fromPHP(['delivery'=>['city'=>'Тула'],'delivery.city'=>'буквальное имя']);
$rows[]=['Неверное чтение missing','RuntimeException','RuntimeException','get и offsetGet','нет значения'];
$rows[]=['Ключ delivery.city','true','true',$literal->get('delivery.city'),$literal->get('delivery')->get('city')];
$checks=['missing_not_null'=>$states[0]===[false,false,'нет поля','не читаем'],
'present_null'=>$states[1]===[true,true,'NULL','NULL'],'zero_kept'=>$states[2]===[true,true,'0','0'],
'missing_get_throws'=>$missingGet,'missing_offset_throws'=>$missingOffset,
'literal_key_not_path'=>$literal->get('delivery.city')==='буквальное имя' && $literal->get('delivery')->get('city')==='Тула'];
bd119Report('mongodb119-documents-optional-fields', ['Ситуация', 'has', 'offsetExists', 'get', 'Чтение [] / вложенного поля'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-optional-fields: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-optional-fields: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Добавьте insurance=false и проверьте has=true, get=false. Затем задайте правило приложения: разрешено ли boolean для денежной доплаты? Проверка наличия не заменяет проверку типа.
Практический вопрос: How to properly convert MongoDB BSON into PHP Object. Разработчик читает необязательное описание и ожидает null вместо ошибки отсутствующего поля. Современный урок отдельно показывает has/get, missing, null и ноль; исторический библиотечный код не копируется. Обсуждение задаёт ситуацию, а актуальные правила проверены по PHP.net и документации MongoDB; код и данные здесь оригинальные.
Изменить адрес в новой копии, сохранив исходный документ
Менеджер исправил адрес, а для аудита нужен прежний вариант. Неизменяемый Document позволяет сохранить исходник; новую версию удобно собрать через явную PHP-копию.
Исходные данные
Тула, Мира, 5; внутренняя заметка склада; contact=null. Новая версия: Казань, Баумана, 8, без внутренней заметки.
- Оригинал Document: Тула
- Прямая запись/удаление → LogicException
- toPHP: изменяемая PHP-копия
- Меняем два поля и удаляем заметку
- fromPHP: новый Document
- Оригинал остаётся прежним
Короткое действие
$copy = $original->toPHP(['root'=>'array', 'document'=>'array', 'array'=>'array']);
$copy['delivery']['city'] = 'Казань';
unset($copy['internal_note']);
$edited = MongoDB\BSON\Document::fromPHP($copy);
// $original сохранил Тулу. Это изменение PHP-значения, не update в MongoDB.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Действие | Результат |
|---|---|
| Прямое присваивание | LogicException |
| Прямой unset | LogicException |
| Исходный адрес | Тула, Мира, 5 |
| Новая копия | Казань, Баумана, 8 |
| Внутренняя заметка в оригинале | есть |
| Внутренняя заметка в копии | нет |
| toPHP без typeMap | stdClass |
| Несуществующий класс typeMap | InvalidArgumentException |
Разбор по шагам
ArrayAccess у Document разрешает чтение, но offsetSet и offsetUnset всегда выбрасывают LogicException. Наличие синтаксиса [] не обещает поддержку изменения. В полном коде оба ожидаемых отказа показаны явно.
toPHP без typeMap обычно даёт stdClass для корневого/вложенного документа и массив для BSON-списка. В этом сценарии задаём root=document=array="array", чтобы редактировать обычный PHP-массив на каждой нужной глубине.
fromPHP создаёт новое BSON-значение из исправленной копии. Проверяем одновременно новый адрес, отсутствие заметки в копии и сохранность оригинала. contact остаётся присутствующим null, а не исчезает при подготовке.
В typeMap передаются только поддерживаемые значения или классы, реализующие Unserializable. Несуществующее имя класса намеренно вызывает InvalidArgumentException. Для обычной формы достаточно встроенных map-значений, собственный класс не нужен.
Ошибки и границы
Превращение всех документов в PHP-массивы может стереть различие пустого {} и []. В этом наборе нет пустого вложенного документа; если форма различает эти значения, сохраняйте stdClass/Document для нужных полей. Изменение PHP-копии не является update базы и не решает конфликт одновременных правок.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$original=Document::fromPHP(['order'=>'ORD-119','delivery'=>['city'=>'Тула','street'=>'Мира, 5'],
'internal_note'=>'Позвонить складу','contact'=>null]);
$setBlocked=false;try{$original['delivery']=['city'=>'Казань'];}
catch(MongoDB\Driver\Exception\LogicException $failure){$setBlocked=true;}
$unsetBlocked=false;try{unset($original['internal_note']);}
catch(MongoDB\Driver\Exception\LogicException $failure){$unsetBlocked=true;}
$copy=$original->toPHP(['root'=>'array','document'=>'array','array'=>'array']);
$copy['delivery']['city']='Казань';$copy['delivery']['street']='Баумана, 8';unset($copy['internal_note']);
$edited=Document::fromPHP($copy);
$default=$original->toPHP();
$badMap=false;try{$original->toPHP(['root'=>'ClassThatDoesNotExist119']);}
catch(MongoDB\Driver\Exception\InvalidArgumentException $failure){$badMap=true;}
$rows=[
['Прямое присваивание',$setBlocked?'LogicException':'ошибка'],
['Прямой unset',$unsetBlocked?'LogicException':'ошибка'],
['Исходный адрес',$original->get('delivery')->get('city').', '.$original->get('delivery')->get('street')],
['Новая копия',$edited->get('delivery')->get('city').', '.$edited->get('delivery')->get('street')],
['Внутренняя заметка в оригинале',$original->has('internal_note')?'есть':'нет'],
['Внутренняя заметка в копии',$edited->has('internal_note')?'есть':'нет'],
['toPHP без typeMap',$default instanceof stdClass?'stdClass':'иной тип'],
['Несуществующий класс typeMap',$badMap?'InvalidArgumentException':'ошибка'],
];
$checks=['immutable_set'=>$setBlocked,'immutable_unset'=>$unsetBlocked,
'original_preserved'=>$original->get('delivery')->get('city')==='Тула' && $original->has('internal_note'),
'copy_changed'=>$edited->get('delivery')->get('city')==='Казань' && !$edited->has('internal_note'),
'null_preserved'=>$edited->has('contact') && $edited->get('contact')===null,
'default_stdclass'=>$default instanceof stdClass && $default->delivery instanceof stdClass,'invalid_map'=>$badMap];
bd119Report('mongodb119-documents-edit-address', ['Действие', 'Результат'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-edit-address: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-edit-address: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Сохраните contact=null и измените только улицу. Проверьте, что заметка и город оригинала не изменились. Затем добавьте пустой вложенный документ и сравните typeMap по умолчанию с принудительным array перед обратным кодированием.
Практический вопрос: Convert PHP mongodb findOne result to old associative array?. Преобразование только корня оставляет вложенные контейнеры другого типа. Урок объясняет root/document/array typeMap и явно отличает нынешний Document расширения от BSONDocument библиотеки. Обсуждение задаёт ситуацию, а актуальные правила проверены по PHP.net и документации MongoDB; код и данные здесь оригинальные.
Передать один документ через бинарный BSON-файл без потери типов
Фоновый процесс должен получить ровно один подготовленный документ вместе с типами его цены, идентификатора и счётчика. Для локального файла можно сохранить сырые BSON-байты и прочитать их обратно.
Исходные данные
Артикул MUG-119, заданный ObjectId, цена Decimal128("19.90"), Int64("7"). Файл создаётся с новым случайным именем и удаляется только после чтения/проверки.
Короткое действие
$raw = (string) $document; // Бинарный BSON, не JSON.
$restored = MongoDB\BSON\Document::fromBSON($raw);
$price = $restored->get('price'); // Снова Decimal128.
// Полный пример действительно записывает и читает файл, затем убирает свой файл.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Проверка | Результат |
|---|---|
| Артикул после файла | MUG-119 |
| Цена и её тип | 19.90 / Decimal128 |
| Счётчик и его тип | 7 / Int64 |
| Байты до и после | совпали |
| Обрезанный BSON | UnexpectedValueException |
| Два склеенных документа | UnexpectedValueException |
| Учебный временный файл | удалён |
Разбор по шагам
__toString у Document возвращает BSON, а не человекочитаемый JSON. В PHP string может содержать бинарные байты, включая нули. Поэтому результат нельзя просто echo в HTML, а длина строки здесь измеряется в байтах.
Режим x+b не перезаписывает существующий файл. Флаг владения появляется после успешного fopen. Проверяется длина записи, затем данные читаются из того же собственного файла; finally закрывает дескриптор и удаляет только известное имя.
fromBSON требует один BSON-документ. Обрезанная строка и две подряд склеенные записи отклоняются UnexpectedValueException. Для потока многих BSON-документов нужна отдельная обработка границ, а не один fromBSON на весь поток.
Сравниваются реальные байты и типы после чтения: Decimal128, ObjectId и Int64. Маленький Int64 не превращается в обычный int при get. Для удобного просмотра данные дополнительно преобразуются в Canonical Extended JSON в metrics.json.
Ошибки и границы
Это сохранение одного сообщения, не резервное копирование базы: здесь нет индексов, коллекций, согласованного состояния всей системы или восстановления сервера. Внешний файл сначала ограничивают по размеру, проверяют происхождение и обрабатывают отказ декодирования. Совпадение SHA256 в локальном отчёте не является цифровой подписью.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$document=Document::fromPHP(['sku'=>'MUG-119','_id'=>new MongoDB\BSON\ObjectId('65a000000000000000000119'),
'price'=>new MongoDB\BSON\Decimal128('19.90'),'count'=>new MongoDB\BSON\Int64('7')]);
$raw=(string)$document;$path=__DIR__.'/snapshot-'.bin2hex(random_bytes(8)).'.bson';$handle=null;$owned=false;
try{
$handle=fopen($path,'x+b');
if($handle===false){throw new RuntimeException('Cannot create own BSON file');}
$owned=true;
if(fwrite($handle,$raw)!==strlen($raw) || !fflush($handle) || !rewind($handle)){throw new RuntimeException('Incomplete BSON write');}
$read=stream_get_contents($handle);
if($read===false){throw new RuntimeException('Cannot read BSON file');}
$restored=Document::fromBSON($read);
$invalid=false;try{Document::fromBSON(substr($read,0,-1));}
catch(MongoDB\Driver\Exception\UnexpectedValueException $failure){$invalid=true;}
$two=false;try{Document::fromBSON($read.$read);}
catch(MongoDB\Driver\Exception\UnexpectedValueException $failure){$two=true;}
$rows=[
['Артикул после файла',$restored->get('sku')],
['Цена и её тип',(string)$restored->get('price').' / Decimal128'],
['Счётчик и его тип',(string)$restored->get('count').' / Int64'],
['Байты до и после',$read===$raw && (string)$restored===$raw?'совпали':'различаются'],
['Обрезанный BSON',$invalid?'UnexpectedValueException':'ошибка'],
['Два склеенных документа',$two?'UnexpectedValueException':'ошибка'],
];
$checks=['file_roundtrip'=>$read===$raw && (string)$restored===$raw,
'id_preserved'=>$restored->get('_id') instanceof MongoDB\BSON\ObjectId && (string)$restored->get('_id')==='65a000000000000000000119',
'decimal_preserved'=>$restored->get('price') instanceof MongoDB\BSON\Decimal128 && (string)$restored->get('price')==='19.90',
'int64_preserved'=>$restored->get('count') instanceof MongoDB\BSON\Int64 && (string)$restored->get('count')==='7',
'truncated_rejected'=>$invalid,'multiple_rejected'=>$two];
$details=['raw_bytes'=>strlen($raw),'raw_sha256'=>hash('sha256',$raw),
'canonical_for_inspection'=>$restored->toCanonicalExtendedJSON()];
}finally{
if(is_resource($handle)){fclose($handle);}
if($owned && !unlink($path)){throw new RuntimeException('Cannot remove own BSON file');}
}
$checks['owned_file_removed']=!file_exists($path);
$rows[]=['Учебный временный файл',$checks['owned_file_removed']?'удалён':'остался'];
bd119Report('mongodb119-documents-binary-archive', ['Проверка', 'Результат'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-binary-archive: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-binary-archive: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Измените цену на Decimal128("0.10") и повторите: тип и две десятичные цифры должны сохраниться. Затем передайте fromBSON обрезанную копию байтов в памяти; исходный файл/документ не исправляйте угадыванием.
Сохранить различие int32 и Int64 при обмене Extended JSON
Два сервиса договорились, что счётчик имеет BSON-тип Int64, даже если его значение сейчас 7. Читаемый JSON без маркера ширины может вернуть другое представление при обратном импорте.
Исходные данные
Вход содержит small как $numberInt="7", wide как $numberLong="7", Decimal128-цену "19.90" и пустой документ. Всё создаётся из заранее заданной Extended JSON-строки.
- fromJSON распознаёт маркеры BSON
- wide становится Int64("7")
- Canonical сохраняет $numberLong
- Обратный fromJSON возвращает Int64
- Relaxed пишет число 7
- Повторное чтение Relaxed даёт int32 / PHP int
Короткое действие
$doc = MongoDB\BSON\Document::fromJSON('{"wide":{"$numberLong":"7"}}');
$canonical = $doc->toCanonicalExtendedJSON(); // Содержит $numberLong.
$restored = MongoDB\BSON\Document::fromJSON($canonical);
// get('wide') возвращает Int64 даже для маленького значения 7.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Путь значения | Результат |
|---|---|
| Исходное wide | 7 / MongoDB\BSON\Int64 |
| Canonical: маркер wide | $numberLong = 7 |
| После Canonical | 7 / MongoDB\BSON\Int64 |
| Relaxed: wide | int = 7 |
| После Relaxed | 7 / int |
| Обычный json_decode для $numberLong | array |
| Цена после обоих форматов | 19.90 / 19.90 |
| Незавершённый JSON | UnexpectedValueException |
Разбор по шагам
Extended JSON — договор поверх JSON, где специальные объекты обозначают BSON-типы. Document::fromJSON понимает эти маркеры. Обычный json_decode видит у wide PHP-массив с ключом $numberLong: он не создаёт Int64 автоматически.
Canonical Extended JSON ставит сохранение типов выше краткости. В примере int32 и int64 имеют разные маркеры, поэтому обратный fromJSON сохраняет различие. Это важно для переноса типизированного сообщения между инструментами.
Relaxed Extended JSON удобнее читать: ряд чисел записывается обычными JSON-числами. Здесь маленькое Int64("7") после такого кругового преобразования становится int32, который get отдаёт PHP-int. Числовое значение то же, а исходный тип уже другой.
Relaxed всё ещё Extended JSON: Decimal128, ObjectId и другие типы могут сохранять специальные маркеры. Это не обещание, что любой frontend ждёт ровно такую структуру. Для публичного API можно отдельно сформировать согласованные строки цены/ID, как в главе о BSON-значениях.
Ошибки и границы
Маркер $numberLong — часть формата, не оператор запроса. Не передавайте импортированный документ целиком в фильтр или update без разрешённой схемы. Парсер проверяет формат, но не смысл товара, валюту или права. Здесь используется точный небольшой Int64; JSON-числа больших значений также ограничены возможностями принимающего языка.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$input='{"sku":"MUG-119","small":{"$numberInt":"7"},"wide":{"$numberLong":"7"},"price":{"$numberDecimal":"19.90"},"empty":{}}';
$document=Document::fromJSON($input);
$canonical=$document->toCanonicalExtendedJSON();$relaxed=$document->toRelaxedExtendedJSON();
$fromCanonical=Document::fromJSON($canonical);$fromRelaxed=Document::fromJSON($relaxed);
$c=json_decode($canonical,true,512,JSON_THROW_ON_ERROR);$r=json_decode($relaxed,true,512,JSON_THROW_ON_ERROR);
$malformed=false;try{Document::fromJSON('{"sku":');}
catch(MongoDB\Driver\Exception\UnexpectedValueException $failure){$malformed=true;}
$plain=json_decode($input,true,512,JSON_THROW_ON_ERROR);
$rows=[
['Исходное wide',bd119Display($document->get('wide')).' / '.get_debug_type($document->get('wide'))],
['Canonical: маркер wide',array_key_first($c['wide']).' = '.$c['wide']['$numberLong']],
['После Canonical',(string)$fromCanonical->get('wide').' / '.get_debug_type($fromCanonical->get('wide'))],
['Relaxed: wide',get_debug_type($r['wide']).' = '.(string)$r['wide']],
['После Relaxed',(string)$fromRelaxed->get('wide').' / '.get_debug_type($fromRelaxed->get('wide'))],
['Обычный json_decode для $numberLong',get_debug_type($plain['wide'])],
['Цена после обоих форматов',(string)$fromCanonical->get('price').' / '.(string)$fromRelaxed->get('price')],
['Незавершённый JSON',$malformed?'UnexpectedValueException':'ошибка'],
];
$checks=['input_int64'=>$document->get('wide') instanceof MongoDB\BSON\Int64,
'canonical_markers'=>$c['small']['$numberInt']==='7' && $c['wide']['$numberLong']==='7',
'canonical_type_roundtrip'=>$fromCanonical->get('wide') instanceof MongoDB\BSON\Int64 && (string)$fromCanonical->get('wide')==='7',
'relaxed_loses_small_int64_width'=>is_int($fromRelaxed->get('wide')) && $fromRelaxed->get('wide')===7,
'ordinary_decode_not_bson'=>is_array($plain['wide']),
'price_preserved'=>$fromCanonical->get('price') instanceof MongoDB\BSON\Decimal128 && $fromRelaxed->get('price') instanceof MongoDB\BSON\Decimal128,
'empty_document_preserved'=>$fromCanonical->get('empty') instanceof Document,
'bad_json_rejected'=>$malformed];
$details=['canonical'=>$canonical,'relaxed'=>$relaxed];
bd119Report('mongodb119-documents-extended-exchange', ['Путь значения', 'Результат'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-extended-exchange: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-extended-exchange: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Сравните Canonical и Relaxed для Int64("42"). Требование хранить исходный BSON-тип означает выбор Canonical или raw BSON. Если получателю нужна только строка для интерфейса, договоритесь об этом явно, не называя её Int64.
Практический вопрос: How can I force a numeral to be stored NumberLong() in mongo using the php mongo driver?. После копирования небольшого числа теряется исходный NumberLong. Урок показывает сохранение Int64 через Canonical и изменение типа после Relaxed на действующем API; старый ответ не считается нормативным. Обсуждение задаёт ситуацию, а актуальные правила проверены по PHP.net и документации MongoDB; код и данные здесь оригинальные.
Перебрать документ и подготовить разрешённые поля для экрана
Экран заказа должен показать четыре согласованных поля, но входной документ содержит ещё внутренний токен. Перебор нужен для подготовки понятного представления с явным списком допустимых полей.
Исходные данные
sku=MUG-119, title="<Кружка>", quantity=2, note=null, internal_token. Имя с угловыми скобками позволяет увидеть, что HTML показывает текст, а не исполняет разметку.
- fromJSON создаёт Document
- getIterator возвращает BSON Iterator
- foreach получает имя и значение
- Разрешены sku/title/quantity/note
- NULL сохраняется, internal_token исключён
- HTML экранирует значения, JSON следует выбранному договору
Короткое действие
foreach ($document->getIterator() as $name => $value) {
if (in_array($name, ['sku', 'title', 'quantity', 'note'], true)) {
$public[$name] = $value;
}
}
// Для HTML значение отдельно экранируется htmlspecialchars, как в result.html.Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Поле | Тип | Значение |
|---|---|---|
| sku | string | MUG-119 |
| title | string | <Кружка> |
| quantity | int | 2 |
| note | null | NULL |
| internal_token | исключён | не выводим |
Разбор по шагам
getIterator возвращает MongoDB\BSON\Iterator. foreach ($iterator as $key => $value) последовательно даёт имя поля и его значение. Это итератор одного документа, не сетевой Cursor списка документов.
Порядок исходных полей фиксирован нашим входом и проверяется для этого примера. Если интерфейсу нужен другой порядок, задайте его явно по набору колонок; не превращайте порядок хранения в скрытое бизнес-правило.
Проверка allowlist выполняется до добавления поля в публичный массив. Значение null не удаляется. Строгое сравнение in_array(..., true) сопоставляет именно имена полей, а не автоматически приведённые значения.
Результат собирается заново в Document и преобразуется в два Extended JSON-представления: в Canonical quantity получает $numberInt, в Relaxed остаётся числом. Отдельный HTML-вывод экранирует текст htmlspecialchars; BSON/JSON не выполняют эту задачу за HTML.
Ошибки и границы
Allowlist на экране дополняет, но не заменяет серверную projection: закрытые поля по возможности вообще не запрашивают из базы. Этот локальный пример получает уже готовое сообщение. Итератор не делает произвольный объект безопасным и не обещает меньшую память для любого размера документа.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
$document=Document::fromJSON('{"sku":"MUG-119","title":"<Кружка>","quantity":2,"note":null,"internal_token":"do-not-display"}');
$allow=['sku','title','quantity','note'];$rows=[];$public=[];$seen=[];
$iterator=$document->getIterator();
foreach($iterator as $key=>$value){
$seen[]=$key;
if(!in_array($key,$allow,true)){continue;}
$public[$key]=$value;
$rows[]=[$key,get_debug_type($value),bd119Display($value)];
}
$publicDocument=Document::fromPHP($public);
$relaxed=$publicDocument->toRelaxedExtendedJSON();$canonical=$publicDocument->toCanonicalExtendedJSON();
$plain=json_decode($relaxed,true,512,JSON_THROW_ON_ERROR);$typed=json_decode($canonical,true,512,JSON_THROW_ON_ERROR);
$rows[]=['internal_token','исключён','не выводим'];
$checks=['bson_iterator'=>$iterator instanceof MongoDB\BSON\Iterator,
'visited_source_fields'=>$seen===['sku','title','quantity','note','internal_token'],
'allowlist_only'=>array_keys($public)===['sku','title','quantity','note'],
'null_not_dropped'=>array_key_exists('note',$public) && $public['note']===null,
'private_field_omitted'=>!$publicDocument->has('internal_token') && !array_key_exists('internal_token',$plain),
'text_value_kept'=>$plain['title']==='<Кружка>',
'canonical_numeric_marker'=>$typed['quantity']['$numberInt']==='2'];
$details=['public_relaxed'=>$relaxed,'public_canonical'=>$canonical];
bd119Report('mongodb119-documents-audit-fields', ['Поле', 'Тип', 'Значение'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-audit-fields: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-audit-fields: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Это локальный BSON-кодек: соединение с базой не создаётся.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Добавьте входное поле supplier_cost и оставьте allowlist прежним: поле не должно попасть в результат. Затем включите новое разрешённое поле в список и задайте его понятную подпись/правило отображения.
Прочитать BSON Document из базы только с нужными полями
Для карточки товара нужны название, цена и город доставки. Не требуется получать внутреннюю заметку, а затем вычищать весь большой результат в PHP.
Исходные данные
В собственной коллекции два товара; запрос выбирает активный _id=101, возвращает только sku/title/price/delivery.city и максимум один документ. Второй товар не подходит фильтру.
- Записываем два собственных учебных товара
- Фильтр _id=101 и active
- Projection возвращает четыре поля
- typeMap root=bson → Document
- Читаем значения и строим локальную копию
- Повторный запрос доказывает: копия не изменила базу
Короткое действие
$cursor = $manager->executeQuery($namespace, new MongoDB\Driver\Query(
['_id'=>101, 'status'=>'active'],
['projection'=>['_id'=>0,'sku'=>1,'title'=>1,'price'=>1], 'limit'=>1]
));
$cursor->setTypeMap(['root'=>'bson']);
$document = $cursor->toArray()[0]; // Полный код проверяет, что документ найден.
$title = $document->get('title'); // КружкаОбъекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.
Что получится
| Действие | Результат |
|---|---|
| Выбранный товар | Кружка |
| Цена | 19.90 |
| Город | Тула |
| Пришедшие поля | delivery, price, sku, title |
| Закрытая заметка | не получена |
| Изменение/удаление на Document | оба LogicException |
| Локальная копия без цены | Кружка для подарка / цены нет |
| Повторное чтение базы | Кружка / 19.90 |
| После BSON-кеша | MUG-119 |
Разбор по шагам
BulkWrite принимает подготовленный Document, но запись происходит только на executeBulkWrite. fromPHP сам по себе не обращается к серверу. Индекс _id уже есть у коллекции; запрос задаёт точный идентификатор и дополнительное условие статуса.
Projection — отбор полей сервером. _id явно исключён, delivery.city здесь действительно серверный путь внутрь документа. limit=1 ограничивает количество документов, maxTimeMS относится к серверной части запроса. Результат маленький, поэтому toArray здесь ограничен одним элементом.
setTypeMap(["root"=>"bson","document"=>"bson","array"=>"bson"]) просит низкоуровневый драйвер вернуть контейнеры расширения. Корень и delivery будут Document. Строка "bson" — встроенное значение type map, а не произвольное имя класса Unserializable.
Из полученного документа нельзя присвоить title или удалить price: оба метода отказывают. Через toPHP создаётся локальная копия для предпросмотра. Повторный запрос показывает прежние Кружку и 19.90 — никакого update в примере не было.
Дополнительно сохраняется бинарная форма маленькой проекции в памяти и восстанавливается через fromBSON. Это другой полезный случай того же механизма: передать полученную карточку внутреннему обработчику, сохраняя Decimal128.
Ошибки и границы
Это отдельная учебная коллекция, которая удаляется в finally. Настоящий сервис отдельно проверяет права пользователя на товар и доступные поля. Изменение имени в интерфейсе надо сохранять явным update с правилами конкуренции; наличие новой локальной копии не является подтверждением записи.
Полная самостоятельная программа и архив
<?php
declare(strict_types=1);
require __DIR__.'/bd119-helper.php';
use MongoDB\BSON\Document;
$runtime=bd119Require();$details=[];
[$manager,$database]=bd119Manager();
$runtime['server']=bd119Command($manager,'admin',['buildInfo'=>1])[0]['version'];
$runtime['execution']='database';
$collection='mongodb119_document_'.bin2hex(random_bytes(8));$namespace=$database.'.'.$collection;$owned=false;
try{
if(bd119Exists($manager,$database,$collection)){throw new RuntimeException('Fixture collision');}
bd119Command($manager,$database,['create'=>$collection],true);$owned=true;
$bulk=new MongoDB\Driver\BulkWrite(['ordered'=>true]);
$bulk->insert(Document::fromPHP(['_id'=>101,'sku'=>'MUG-119','title'=>'Кружка','status'=>'active',
'price'=>new MongoDB\BSON\Decimal128('19.90'),'delivery'=>['city'=>'Тула'],'internal_note'=>'Не для витрины']));
$bulk->insert(Document::fromPHP(['_id'=>102,'sku'=>'TEA-119','title'=>'Чай','status'=>'inactive',
'price'=>new MongoDB\BSON\Decimal128('9.50'),'internal_note'=>'Не для витрины']));
$inserted=$manager->executeBulkWrite($namespace,$bulk)->getInsertedCount();
$read=function() use($manager,$namespace): MongoDB\BSON\Document {
$cursor=$manager->executeQuery($namespace,new MongoDB\Driver\Query(
['_id'=>101,'status'=>'active'],
['projection'=>['_id'=>0,'sku'=>1,'title'=>1,'price'=>1,'delivery.city'=>1],'limit'=>1,'maxTimeMS'=>1000]));
$cursor->setTypeMap(['root'=>'bson','document'=>'bson','array'=>'bson']);
$found=$cursor->toArray();
if(count($found)!==1 || !$found[0] instanceof MongoDB\BSON\Document){throw new RuntimeException('Expected one projected BSON Document');}
return $found[0];
};
$document=$read();$keys=[];
foreach($document->getIterator() as $key=>$value){$keys[]=$key;}sort($keys);
$setBlocked=false;try{$document->offsetSet('title','Изменено');}
catch(MongoDB\Driver\Exception\LogicException $failure){$setBlocked=true;}
$unsetBlocked=false;try{$document->offsetUnset('price');}
catch(MongoDB\Driver\Exception\LogicException $failure){$unsetBlocked=true;}
$copy=$document->toPHP(['root'=>'array','document'=>'array','array'=>'array']);
$copy['title']='Кружка для подарка';unset($copy['price']);$preview=Document::fromPHP($copy);
$cache=Document::fromBSON((string)$document);$again=$read();
$rows=[
['Выбранный товар',$document->offsetGet('title')],
['Цена',(string)$document->get('price')],
['Город',$document->get('delivery')->get('city')],
['Пришедшие поля',implode(', ',$keys)],
['Закрытая заметка',$document->offsetExists('internal_note')?'ошибка':'не получена'],
['Изменение/удаление на Document',($setBlocked&&$unsetBlocked)?'оба LogicException':'ошибка'],
['Локальная копия без цены',$preview->get('title').' / '.($preview->has('price')?'есть цена':'цены нет')],
['Повторное чтение базы',$again->get('title').' / '.(string)$again->get('price')],
['После BSON-кеша',$cache->get('sku')],
];
$checks=['inserted_two'=>$inserted===2,'projected_document'=>$document instanceof Document,
'only_needed_fields'=>$keys===['delivery','price','sku','title'] && !$document->has('internal_note'),
'typed_value'=>$document->get('price') instanceof MongoDB\BSON\Decimal128,
'nested_bson_document'=>$document->get('delivery') instanceof Document,
'immutable_set'=>$setBlocked,'immutable_unset'=>$unsetBlocked,
'copy_is_local'=>$preview->get('title')==='Кружка для подарка' && !$preview->has('price') && $again->get('title')==='Кружка' && (string)$again->get('price')==='19.90',
'binary_cache_roundtrip'=>$cache->get('sku')==='MUG-119' && (string)$cache===(string)$document];
}finally{if($owned){bd119Command($manager,$database,['drop'=>$collection],true);}}
$checks['owned_collection_removed']=!bd119Exists($manager,$database,$collection);
bd119Report('mongodb119-documents-projected-catalog', ['Действие', 'Результат'], $rows, $checks, $runtime, $details);
echo 'mongodb119-documents-projected-catalog: saved result.html and result.json
';
Ожидаемый результат
mongodb119-documents-projected-catalog: saved result.html and result.json
Запустите php example.php и откройте result.html. Архив включает helper и полный README. Здесь действительно используется своя учебная коллекция MongoDB, затем она удаляется.
Открыть фактический результат HTML · Скачать JSON результата
Упражнение с ориентиром результата. Добавьте третий товар и сохраните фильтр _id=101: вывод остаётся одним товаром. Уберите delivery.city из projection и сначала проверьте has("delivery") перед чтением. Не заменяйте запрос выгрузкой всей коллекции ради поиска в PHP.
Полный договор typeMap для toPHP
Карта определяет форму PHP-контейнера после декодирования. Она не меняет схему MongoDB и не записывает ничего на сервер. В toPHP и Cursor::setTypeMap используется один договор преобразования.
| Область | Что выбирает |
|---|---|
| root | Только верхний BSON-документ |
| document | Все вложенные BSON-документы |
| array | BSON-массивы |
| fieldPaths | Отдельные пути; $ обозначает элемент массива, например addresses.$ |
| Значение карты | Результат и ограничения |
|---|---|
| не задано / null | По умолчанию массив BSON → PHP array; документ без специального __pclass → stdClass. |
| array | Документ или BSON-массив → PHP array; специальное восстановление __pclass не применяется. |
| object / stdClass | Документ или BSON-массив → stdClass; специальное восстановление __pclass не применяется. |
| bson | Документ → Document, список → PackedArray. Только root/document/array, не fieldPaths; __pclass не меняет этот выбор. |
| имя другого класса | Класс должен существовать, быть конкретным и реализовать Unserializable; иначе InvalidArgumentException. |
Специальное поле __pclass имеет смысл только как BSON Binary подтипа 0x80. По стандартным правилам существующий Persistable-класс из него может восстанавливаться через bsonUnserialize; иначе используется stdClass. При явном пользовательском классе карты подходящий Persistable-класс из __pclass имеет приоритет. Для этой механики projection должна сохранить __pclass. Для форм и чужих сообщений проще выбрать явный безопасный контейнер; не принимайте имя класса карты от клиента.
BSON int64 в Document::toPHP возвращается Int64; карта управляет контейнерами, а не обещает превратить все BSON-значения в скаляры. У BSON технически возможны повторяющиеся имена полей, но их нельзя генерировать: сервер/драйвер могут вести себя неопределённо, а PHP-массив/объект не хранит дубликаты ключей и потеряет часть данных.
Принудительный array удобен для копии адреса, однако пустой документ {} и пустой список [] тогда могут стать одинаковым PHP-массивом. Для сохранения различия используйте стандартные объекты или bson. Подробные первичные правила: сериализация и десериализация PHP/BSON.
Canonical и Relaxed: представления BSON-типов
Ниже — справочная форма значения поля для BSON-типов из официальных примеров двух методов. Здесь показана структура представления, а не отдельный набор выполненных программ. Значения данных отличаются от примеров PHP.net; работа обоих методов реально выполняется в binary-archive, extended-exchange и audit-fields.
| BSON-значение | Canonical Extended JSON | Relaxed Extended JSON |
|---|---|---|
| null | null | null |
| boolean | true / false | true / false |
| string | "Кружка" | "Кружка" |
| int32, 7 | {"$numberInt":"7"} | 7 |
| int64, 7 | {"$numberLong":"7"} | 7 |
| double, 7.5 | {"$numberDouble":"7.5"} | 7.5 |
| double NaN | {"$numberDouble":"NaN"} | {"$numberDouble":"NaN"} |
| double ±Infinity | {"$numberDouble":"Infinity"} / "-Infinity" | Те же маркеры нечисловых JSON-значений |
| BSON array | ["Кружка","Чай"] | ["Кружка","Чай"] |
| BSON document | {"city":"Тула"} | {"city":"Тула"} |
| ObjectId | {"$oid":"65a000000000000000000119"} | Тот же $oid |
| Decimal128 | {"$numberDecimal":"19.90"} | Тот же $numberDecimal |
| Binary | {"$binary":{"base64":"AA==","subType":"00"}} | Тот же $binary |
| Date, эпоха Unix | {"$date":{"$numberLong":"0"}} | {"$date":"1970-01-01T00:00:00Z"} |
| Timestamp | {"$timestamp":{"t":100,"i":2}} | Тот же $timestamp |
| Regex | {"$regularExpression":{"pattern":"mug","options":"i"}} | Тот же $regularExpression |
| JavaScript | {"$code":"return 2;"} | Тот же $code |
| JavaScript со scope | {"$code":"return x;","$scope":{"x":{"$numberInt":"2"}}} | $code и $scope; вложенное число может быть обычным 2 |
| MinKey | {"$minKey":1} | {"$minKey":1} |
| MaxKey | {"$maxKey":1} | {"$maxKey":1} |
Для дат Relaxed использует ISO-представление в поддерживаемом диапазоне годов 1970–9999; вне него требуется числовая форма миллисекунд. NaN/Infinity не являются допустимыми обычными JSON-числами, поэтому сохраняются специальные маркеры. Это свойства формата, а не разрешение использовать NaN как цену.
Число 7 в Relaxed не сообщает, было ли оно int32 или int64. Canonical сохраняет эту информацию, но не обещает исходные пробелы JSON. Raw BSON от __toString вообще бинарный. Для HTML все эти текстовые формы дополнительно экранируются; для приложения заранее выбирают формат, который понимает получатель.
Все 15 методов BSON Document
Каждая карточка сохраняет контракт соответствующей страницы PHP.net: сигнатуру, параметры, результат, ошибки и версии, затем показывает два разных применения из самостоятельных сценариев.
| Метод | Для чего нужен |
|---|---|
| MongoDB\BSON\Document::__construct | Понять, почему Document создают фабрикой, а не через new. |
| MongoDB\BSON\Document::fromPHP | Создать BSON-документ из PHP-массива или объекта. |
| MongoDB\BSON\Document::fromBSON | Восстановить ровно один документ из бинарной BSON-строки. |
| MongoDB\BSON\Document::fromJSON | Преобразовать Extended JSON в BSON Document. |
| MongoDB\BSON\Document::get | Получить значение поля по точному имени. |
| MongoDB\BSON\Document::getIterator | Получить итератор полей одного BSON-документа. |
| MongoDB\BSON\Document::has | Проверить присутствие поля, независимо от его значения. |
| MongoDB\BSON\Document::offsetExists | Проверить присутствие ключа через ArrayAccess. |
| MongoDB\BSON\Document::offsetGet | Прочитать поле синтаксисом ArrayAccess. |
| MongoDB\BSON\Document::offsetSet | Увидеть запрет изменения Document через ArrayAccess. |
| MongoDB\BSON\Document::offsetUnset | Увидеть запрет удаления поля из Document. |
| MongoDB\BSON\Document::toCanonicalExtendedJSON | Получить текстовый обмен с сохранением различий BSON-типов. |
| MongoDB\BSON\Document::toPHP | Получить PHP-представление и управлять типами контейнеров. |
| MongoDB\BSON\Document::toRelaxedExtendedJSON | Получить более короткое Extended JSON-представление для чтения. |
| MongoDB\BSON\Document::__toString | Получить сырые байты BSON-документа. |
Выбрать формат для своей границы данных
Выберите формат по границе задачи: Document для чтения неизменяемого BSON, PHP-копия для правки разрешённых полей, raw BSON для бинарной передачи одного документа, Canonical для сохранения типов в тексте, Relaxed для более короткого представления по согласованному договору. Ни одно такое преобразование само по себе не обновляет MongoDB.
Далее: списки PackedArray и итерация, ObjectId, UTCDateTime и Decimal128, реальное условное обновление и ограниченный запрос под нужный экран.
Глава охватывает перечисленные 15 методов Document. Сериализуемые пользовательские классы, все BSON-скалярные классы, резервное копирование целой базы и полный справочник MongoDB требуют отдельных материалов; успешное преобразование одного документа не выдаётся за покрытие этих тем.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
MongoDB\BSON\Document::__constructПонять, почему Document создают фабрикой, а не через new.
mongodb 1.16.0+ · mongodb
final private MongoDB\BSON\Document::__construct()Понять, почему Document создают фабрикой, а не через new.
final private MongoDB\BSON\Document::__construct()Параметры
Параметров нет.
Что возвращает
Конструктор закрыт и напрямую недоступен. Создание выполняют статические fromPHP, fromBSON или fromJSON.
Ошибки и ограничения
Попытка new Document() снаружи класса даёт ошибку доступа PHP Error; это не способ создать пустой документ.
Версия
mongodb 1.16.0+
Применение 1: Подготовить снимок данных формы
Document::fromPHP(['order'=>'ORD-119']);Фабрика создала документ; намеренная попытка new поймана как Error.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Принять типизированное сообщение интеграции
Document::fromJSON('{"wide":{"$numberLong":"7"}}');JSON-фабрика создаёт Document и Int64 внутри него; отдельный вызов конструктора не нужен.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::fromPHPСоздать BSON-документ из PHP-массива или объекта.
mongodb 1.16.0+ · mongodb
final public static MongoDB\BSON\Document::fromPHP(object|array $value): MongoDB\BSON\DocumentСоздать BSON-документ из PHP-массива или объекта.
final public static MongoDB\BSON\Document::fromPHP(object|array $value): MongoDB\BSON\DocumentПараметры
| Параметр | Смысл |
|---|---|
| value: object|array | Исходные поля документа. Числовые ключи корневого PHP-массива превращаются в строковые ключи документа. |
Что возвращает
Новый Document. Корень всегда документ; вложенные последовательные списки и документы сохраняют разные BSON-формы по правилам сериализации.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. Фабрика не проверяет прикладную схему, не записывает данные в MongoDB и не делает произвольные входные поля разрешёнными.
Версия
mongodb 1.16.0+
У обычного объекта сериализуются публичные свойства. Поддерживаемые BSON-типы и Serializable/Persistable имеют собственные правила; это разобрано в разделе сериализации PHP/BSON. Не сериализуйте произвольный бизнес-объект вместо явного набора разрешённых полей.
Применение 1: Снимок заказа до изменения формы
$document = Document::fromPHP($input);Исходный PHP-массив меняется на Казань; Document сохраняет Тулу.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Новая версия исправленного адреса
$edited = Document::fromPHP($copy);Изменяемая копия становится новым Document; оригинал и его внутренняя заметка сохранены.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::fromBSONВосстановить ровно один документ из бинарной BSON-строки.
mongodb 1.16.0+ · mongodb
final public static MongoDB\BSON\Document::fromBSON(string $bson): MongoDB\BSON\DocumentВосстановить ровно один документ из бинарной BSON-строки.
final public static MongoDB\BSON\Document::fromBSON(string $bson): MongoDB\BSON\DocumentПараметры
| Параметр | Смысл |
|---|---|
| bson: string | Бинарные байты одного BSON-документа; это не JSON-текст и не набор склеенных документов. |
Что возвращает
Новый Document, сохраняющий BSON-типы входного документа.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. UnexpectedValueException при некорректном BSON или более чем одном документе. Проверка структуры не заменяет ограничение размера/происхождения входа.
Версия
mongodb 1.16.0+
Применение 1: Прочитать сообщение из своего файла
$restored = Document::fromBSON($read);После реальной записи/чтения файла сохранены цена Decimal128 и Int64(7); обрезка и склейка двух документов отклонены.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Восстановить небольшую проекцию из внутреннего кеша
$cache = Document::fromBSON((string) $document);Артикул MUG-119 и тип цены сохраняются после бинарного кругового преобразования полученной из базы карточки.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::fromJSONПреобразовать Extended JSON в BSON Document.
mongodb 1.16.0+ · mongodb
final public static MongoDB\BSON\Document::fromJSON(string $json): MongoDB\BSON\DocumentПреобразовать Extended JSON в BSON Document.
final public static MongoDB\BSON\Document::fromJSON(string $json): MongoDB\BSON\DocumentПараметры
| Параметр | Смысл |
|---|---|
| json: string | JSON/Extended JSON-значение, которое можно представить BSON-документом. Маркеры Extended JSON кодируют специальные BSON-типы. |
Что возвращает
Новый Document. Это не то же преобразование, что json_decode в обычный PHP-массив.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. UnexpectedValueException, если значение нельзя преобразовать в BSON-документ, например из-за синтаксической ошибки.
Версия
mongodb 1.16.0+
Применение 1: Сохранить разрядность счётчика сообщения
$document = Document::fromJSON($input);$numberLong создаёт Int64 даже для 7; ошибка незавершённого JSON явно обработана.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Разобрать сообщение для разрешённых полей экрана
$document = Document::fromJSON('{"sku":"MUG-119","title":"<Кружка>","quantity":2,"note":null,"internal_token":"do-not-display"}');В сценарии строка с sku/title/quantity/note разобрана, затем внутренний токен исключён allowlist перед выводом.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::getПолучить значение поля по точному имени.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::get(string $key): mixedПолучить значение поля по точному имени.
final public MongoDB\BSON\Document::get(string $key): mixedПараметры
| Параметр | Смысл |
|---|---|
| key: string | Точное имя поля. Для вложенности сначала получите вложенный Document; точка не интерпретируется как путь. |
Что возвращает
Значение поля; вложенный документ доступен как Document, список как PackedArray. BSON int64 возвращается объектом MongoDB\BSON\Int64, даже на 64-битном PHP.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. RuntimeException при отсутствующем ключе; присутствующий null является обычным возвращаемым значением.
Версия
mongodb 1.16.0+
Применение 1: Прочитать город доставки
$city = $document->get('delivery')->get('city');Получена Тула, несмотря на последующее изменение исходного PHP-массива.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Различить неизвестную и нулевую доплату
$value = $document->has('insurance') ? $document->get('insurance') : 'нет поля';Таблица отдельно показывает missing, NULL и 0; прямое чтение missing даёт RuntimeException.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::getIteratorПолучить итератор полей одного BSON-документа.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::getIterator(): MongoDB\BSON\IteratorПолучить итератор полей одного BSON-документа.
final public MongoDB\BSON\Document::getIterator(): MongoDB\BSON\IteratorПараметры
Параметров нет.
Что возвращает
MongoDB\BSON\Iterator для обхода всех ключей документа. Это не Cursor результата сетевого запроса.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. UnexpectedValueException, если BSON-итератор невозможно инициализировать.
Версия
mongodb 1.16.0+
Применение 1: Отобрать публичные поля сообщения
foreach ($document->getIterator() as $name => $value) {
// Применить список разрешённых полей.
}В выводе четыре поля, внутренний токен исключён; NULL не потерян.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Проверить фактические поля серверной проекции
foreach ($document->getIterator() as $key => $value) { $keys[] = $key; }Получены только delivery, price, sku и title. Список полей результата не подменяет саму серверную projection.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::hasПроверить присутствие поля, независимо от его значения.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::has(string $key): boolПроверить присутствие поля, независимо от его значения.
final public MongoDB\BSON\Document::has(string $key): boolПараметры
| Параметр | Смысл |
|---|---|
| key: string | Точное имя поля. Для вложенности сначала получите вложенный Document; точка не интерпретируется как путь. |
Что возвращает
true, если ключ присутствует; false, если отсутствует. Значения null, 0 и false сами по себе не означают отсутствия.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов.
Версия
mongodb 1.16.0+
Применение 1: Выбрать правило отсутствующей страховки
$present = $document->has('insurance');Для missing false, для NULL и 0 — true.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Убедиться, что заметка удалена только в новой копии
$original->has('internal_note');
$edited->has('internal_note');Оригинал возвращает true, исправленная копия false.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::offsetExistsПроверить присутствие ключа через ArrayAccess.
mongodb 1.17.0+ · mongodb
final public MongoDB\BSON\Document::offsetExists(mixed $key): boolПроверить присутствие ключа через ArrayAccess.
final public MongoDB\BSON\Document::offsetExists(mixed $key): boolПараметры
| Параметр | Смысл |
|---|---|
| key: mixed | Ключ интерфейса ArrayAccess. В практических примерах используется проверенная строка имени поля. |
Что возвращает
true при наличии ключа, иначе false. Контракт описывает наличие; не подменяйте его проверкой ненулевого значения.
Ошибки и ограничения
На странице метода отдельного списка исключений нет. Для ясного прикладного кода используйте проверенное строковое имя и обычный has; неподдерживаемый вход не следует считать допустимым по одному слову mixed.
Версия
mongodb 1.17.0+
Применение 1: Согласовать доступ через скобки с необязательным полем
$exists = $document->offsetExists('insurance');Присутствующий null остаётся true; после этого [] может вернуть null.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Проверить, что внутренняя заметка не пришла
$exists = $document->offsetExists('internal_note');false подтверждает отсутствие поля в ограниченной серверной проекции.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::offsetGetПрочитать поле синтаксисом ArrayAccess.
mongodb 1.17.0+ · mongodb
final public MongoDB\BSON\Document::offsetGet(mixed $key): mixedПрочитать поле синтаксисом ArrayAccess.
final public MongoDB\BSON\Document::offsetGet(mixed $key): mixedПараметры
| Параметр | Смысл |
|---|---|
| key: mixed | Ключ интерфейса ArrayAccess. В практических примерах используется проверенная строка имени поля. |
Что возвращает
Значение ключа, как у get. Для BSON int64 возвращается MongoDB\BSON\Int64, а не автоматически нативный int.
Ошибки и ограничения
Документация перечисляет InvalidArgumentException при ошибке разбора аргументов. RuntimeException, если ключ отсутствует.
Версия
mongodb 1.17.0+
Применение 1: Прочитать присутствующий NULL через []
$value = $document['insurance'];В примере это null для явно неизвестной страховки и 0 для нулевой; missing сначала отсеивается проверкой.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Получить заголовок выбранного товара
$title = $document->offsetGet('title');Из реально полученного Document читается Кружка; лишние товары не выгружены.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::offsetSetУвидеть запрет изменения Document через ArrayAccess.
mongodb 1.17.0+ · mongodb
final public MongoDB\BSON\Document::offsetSet(mixed $key, mixed $value): voidУвидеть запрет изменения Document через ArrayAccess.
final public MongoDB\BSON\Document::offsetSet(mixed $key, mixed $value): voidПараметры
| Параметр | Смысл |
|---|---|
| key: mixed | Ключ интерфейса ArrayAccess. В практических примерах используется проверенная строка имени поля. |
| value: mixed | Предлагаемое новое значение. Document неизменяем, поэтому запись не выполняется. |
Что возвращает
Сигнатура void описывает интерфейс; успешного изменения Document этим методом нет.
Ошибки и ограничения
Всегда выбрасывает MongoDB\Driver\Exception\LogicException. Синтаксис $document["field"]=... вызывает тот же запрет.
Версия
mongodb 1.17.0+
Применение 1: Исправить адрес без повреждения исходного снимка
$original['delivery'] = ['city'=>'Казань']; // LogicExceptionПрямое изменение отвергается; рабочий путь — toPHP, правка копии, fromPHP.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Подготовить название для предпросмотра
$document->offsetSet('title', 'Изменено'); // LogicExceptionДокумент запроса не меняется. Новое название существует только в отдельно созданной копии, база остаётся прежней.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::offsetUnsetУвидеть запрет удаления поля из Document.
mongodb 1.17.0+ · mongodb
final public MongoDB\BSON\Document::offsetUnset(mixed $key): voidУвидеть запрет удаления поля из Document.
final public MongoDB\BSON\Document::offsetUnset(mixed $key): voidПараметры
| Параметр | Смысл |
|---|---|
| key: mixed | Ключ интерфейса ArrayAccess. В практических примерах используется проверенная строка имени поля. |
Что возвращает
Сигнатура void принадлежит ArrayAccess; успешного удаления из неизменяемого Document нет.
Ошибки и ограничения
Всегда выбрасывает MongoDB\Driver\Exception\LogicException. unset($document["field"]) также не поддерживается.
Версия
mongodb 1.17.0+
Применение 1: Убрать внутреннюю заметку из отправляемой копии
unset($original['internal_note']); // LogicExceptionЗаметка остаётся в исходнике; удаление выполняется лишь в PHP-копии перед новым fromPHP.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Убрать цену из локального варианта карточки
$document->offsetUnset('price'); // LogicExceptionОтказ не является удалением цены в MongoDB. Копия без цены показана отдельно; повторное чтение базы возвращает 19.90.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::toCanonicalExtendedJSONПолучить текстовый обмен с сохранением различий BSON-типов.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::toCanonicalExtendedJSON(): stringПолучить текстовый обмен с сохранением различий BSON-типов.
final public MongoDB\BSON\Document::toCanonicalExtendedJSON(): stringПараметры
Параметров нет.
Что возвращает
Строка Canonical Extended JSON. Формат предпочитает сохранение типов краткости и подходит для обратного преобразования без потери сведений о типах, в том числе различий числовых типов.
Ошибки и ограничения
Отдельный список исключений на странице не приведён. Выход остаётся форматом данных; перед HTML его экранируют. Наличие маркеров типов не проверяет бизнес-схему.
Версия
mongodb 1.16.0+
Маркеры для всех типов, представленных официальным примером, перечислены ниже в таблице форматов. Canonical не обещает побайтовую идентичность произвольного исходного JSON: это типизированное представление BSON.
Формы всех BSON-типов официального примера
Применение 1: Посмотреть типизированное сообщение после чтения файла
$text = $restored->toCanonicalExtendedJSON();В metrics.json видны маркеры цены Decimal128 и счётчика Int64, а не нечитаемые сырые байты.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Передать маленький Int64 без смены ширины
$text = $document->toCanonicalExtendedJSON();
$copy = Document::fromJSON($text);У wide сохраняется $numberLong и после обратного чтения остаётся Int64("7").
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::toPHPПолучить PHP-представление и управлять типами контейнеров.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::toPHP(?array $typeMap = null): array|objectПолучить PHP-представление и управлять типами контейнеров.
final public MongoDB\BSON\Document::toPHP(?array $typeMap = null): array|objectПараметры
| Параметр | Смысл |
|---|---|
| typeMap: ?array | Необязательная карта преобразования корня, вложенных документов, BSON-массивов и отдельных путей. null означает стандартные правила. |
Что возвращает
Декодированное PHP-значение. BSON int64 возвращается MongoDB\BSON\Int64, включая 64-битный PHP. Настройка контейнеров не превращает Decimal128/ObjectId в обычные строки.
Ошибки и ограничения
InvalidArgumentException, если указанный класс нельзя создать или он не реализует MongoDB\BSON\Unserializable. BSON технически может содержать повторяющиеся ключи; так делать нельзя, поведение сервера/драйвера неопределённо, а PHP-массив/объект потеряет повторения.
Версия
mongodb 1.16.0+
Полная таблица областей/значений typeMap приведена ниже. Передаваемый массив — настройки преобразования, не MongoDB query и не инструкция записать изменения.
Все области и значения typeMap
Применение 1: Отредактировать вложенный адрес как PHP-массив
$copy = $original->toPHP(['root'=>'array','document'=>'array','array'=>'array']);Город/улица изменяются в новой копии, исходник остаётся Тула, Мира, 5.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Сделать локальный вариант уже отобранной карточки
$copy = $document->toPHP(['root'=>'array','document'=>'array','array'=>'array']);Копия меняет заголовок и удаляет цену только для предпросмотра; повторный запрос подтверждает неизменность базы.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::toRelaxedExtendedJSONПолучить более короткое Extended JSON-представление для чтения.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::toRelaxedExtendedJSON(): stringПолучить более короткое Extended JSON-представление для чтения.
final public MongoDB\BSON\Document::toRelaxedExtendedJSON(): stringПараметры
Параметров нет.
Что возвращает
Строка Relaxed Extended JSON. Формат чаще использует обычные JSON-примитивы, жертвуя частью точности представления типов ради читаемости и удобства потребителей.
Ошибки и ограничения
Отдельный список исключений на странице не приведён. Relaxed не означает отсутствие BSON-маркеров и не гарантирует сохранение всех числовых типов после roundtrip.
Версия
mongodb 1.16.0+
Таблица форматов ниже сохраняет представления всех BSON-типов из официального примера. Для внешнего API отдельно определите договор ID, даты и суммы вместо ожидания, что любой клиент понимает Extended JSON.
Формы всех BSON-типов официального примера
Применение 1: Понять цену краткого числового вывода
$text = $document->toRelaxedExtendedJSON();Int64("7") записывается числом 7; после fromJSON получен PHP-int, а не исходный Int64.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Отдать согласованные поля маленького отчёта
$text = $publicDocument->toRelaxedExtendedJSON();quantity остаётся обычным числом 2, note=null сохранён, internal_token в созданном публичном документе отсутствует.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
MongoDB\BSON\Document::__toStringПолучить сырые байты BSON-документа.
mongodb 1.16.0+ · mongodb
final public MongoDB\BSON\Document::__toString(): stringПолучить сырые байты BSON-документа.
final public MongoDB\BSON\Document::__toString(): stringПараметры
Параметров нет.
Что возвращает
Строковое представление документа как BSON. (string) $document вызывает этот метод; PHP string здесь бинарный.
Ошибки и ограничения
На странице отдельного списка исключений нет. Это не JSON и не текст для echo в HTML. Для текстового просмотра используйте Canonical/Relaxed Extended JSON.
Версия
mongodb 1.16.0+
Применение 1: Записать типизированное сообщение в бинарный файл
$raw = (string) $document;Байты записаны/прочитаны с реальным файлом и совпали; Decimal128 и Int64 сохранены.
Объяснение и полная самостоятельная программа · Фактическая таблица
Применение 2: Передать проекцию внутреннему обработчику без смены типов
$cache = Document::fromBSON((string) $document);После памяти-кеша снова доступен MUG-119 и типизированная цена; это не обновление записи сервера.
Объяснение и полная самостоятельная программа · Фактическая таблица
Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.
Источники и обсуждения
- MongoDB\BSON\Document::__construct
- MongoDB\BSON\Document::fromPHP
- MongoDB\BSON\Document::fromBSON
- MongoDB\BSON\Document::fromJSON
- MongoDB\BSON\Document::get
- MongoDB\BSON\Document::getIterator
- MongoDB\BSON\Document::has
- MongoDB\BSON\Document::offsetExists
- MongoDB\BSON\Document::offsetGet
- MongoDB\BSON\Document::offsetSet
- MongoDB\BSON\Document::offsetUnset
- MongoDB\BSON\Document::toCanonicalExtendedJSON
- MongoDB\BSON\Document::toPHP
- MongoDB\BSON\Document::toRelaxedExtendedJSON
- MongoDB\BSON\Document::__toString
- Document: класс расширения
- Преобразование PHP/BSON и typeMap
- MongoDB Extended JSON v2
- BSONDocument библиотеки PHP
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


