Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 150 · После BSON-значений и чтения MongoDB через драйвер

MongoDB: BSON Document — поля, копия, файл и Extended JSON

Читать необязательные поля, исправлять отдельную копию, сохранять BSON-типы и получать из базы только нужную карточку.

Зачем документу отдельный тип

Сервис получил заказ: город доставки, позиции, необязательная страховка и цена. Нужно прочитать именно нужные поля, сохранить их типы при передаче и подготовить исправленную копию, не затронув исходник. BSON Document решает задачу представления одного документа; это ещё не коллекция и не запрос к MongoDB.

ЗадачаВходВидимый результат
Снимок доставкиТула в PHP-массивеDocument сохраняет Тулу после изменения исходного массива
Необязательная доплатаmissing / null / 0Три разных состояния, без потери нуля
Исправление адресаТула, Мира, 5Новая копия Казань, Баумана, 8; исходник сохранён
Обмен типизированным счётчикомInt64("7")Canonical сохраняет тип, Relaxed может его сузить
Карточка товараДва товара на сервереОдин Document только с нужными полями
Как представлены данные одного заказа
  1. PHP-массив: order=ORD-119
  2. Document::fromPHP
  3. BSON Document с именами полей
  4. get("delivery") → вложенный Document
  5. get("city") → строка Тула
  6. 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\PackedArrayBSON-список с последовательными позициями; соседняя глава
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-массиве город меняется на Казань.

Действия над этими значениями
  1. PHP: order и delivery.city=Тула
  2. fromPHP создаёт BSON Document
  3. delivery читается как вложенный Document
  4. items читается как PackedArray
  5. Исходный PHP-массив меняется на Казань
  6. 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".

Действия над этими значениями
  1. has проверяет присутствие ключа
  2. offsetExists проверяет тот же факт
  3. Ключ есть → get или [] читает значение
  4. NULL не означает missing
  5. 0 не означает false результата поиска
  6. Для вложенности читаем по одному Document

Короткое действие

if ($document->has('insurance')) {
    $insurance = $document->get('insurance'); // Может быть null или 0.
} else {
    // Поле отсутствует: используйте отдельное правило приложения.
}
// get('delivery.city') ищет буквальное имя, не путь через вложенный Document.

Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.

Что получится

СитуацияhasoffsetExistsgetЧтение [] / вложенного поля
Поле не переданоfalsefalseнет поляне читаем
Явно неизвестноtruetrueNULLNULL
Доплата нольtruetrue00
Неверное чтение missingRuntimeExceptionRuntimeExceptionget и offsetGetнет значения
Ключ delivery.citytruetrueбуквальное имяТула

Разбор по шагам

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-поля не означает, что пользователь вправе его изменять. Точка в ключе здесь иллюстрирует локальный доступ; это не рекомендация проектировать рабочую схему с такими именами.

Полная самостоятельная программа и архив
Отличить неуказанное поле, NULL и нулевую доплатуСамостоятельный пример
<?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, без внутренней заметки.

Действия над этими значениями
  1. Оригинал Document: Тула
  2. Прямая запись/удаление → LogicException
  3. toPHP: изменяемая PHP-копия
  4. Меняем два поля и удаляем заметку
  5. fromPHP: новый Document
  6. Оригинал остаётся прежним

Короткое действие

$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
Прямой unsetLogicException
Исходный адресТула, Мира, 5
Новая копияКазань, Баумана, 8
Внутренняя заметка в оригиналеесть
Внутренняя заметка в копиинет
toPHP без typeMapstdClass
Несуществующий класс typeMapInvalidArgumentException

Разбор по шагам

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"). Файл создаётся с новым случайным именем и удаляется только после чтения/проверки.

Действия над этими значениями
  1. Document с типизированными полями
  2. (string) → бинарные BSON-байты
  3. fopen x+b → свой новый файл
  4. Запись, flush, возврат к началу, чтение
  5. fromBSON восстанавливает один Document
  6. Типы/байты сверены, свой файл удалён

Короткое действие

$raw = (string) $document; // Бинарный BSON, не JSON.
$restored = MongoDB\BSON\Document::fromBSON($raw);
$price = $restored->get('price'); // Снова Decimal128.
// Полный пример действительно записывает и читает файл, затем убирает свой файл.

Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.

Что получится

ПроверкаРезультат
Артикул после файлаMUG-119
Цена и её тип19.90 / Decimal128
Счётчик и его тип7 / Int64
Байты до и послесовпали
Обрезанный BSONUnexpectedValueException
Два склеенных документа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 в локальном отчёте не является цифровой подписью.

Полная самостоятельная программа и архив
Передать один документ через бинарный BSON-файл без потери типовСамостоятельный пример
<?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-строки.

Действия над этими значениями
  1. fromJSON распознаёт маркеры BSON
  2. wide становится Int64("7")
  3. Canonical сохраняет $numberLong
  4. Обратный fromJSON возвращает Int64
  5. Relaxed пишет число 7
  6. Повторное чтение 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.

Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.

Что получится

Путь значенияРезультат
Исходное wide7 / MongoDB\BSON\Int64
Canonical: маркер wide$numberLong = 7
После Canonical7 / MongoDB\BSON\Int64
Relaxed: wideint = 7
После Relaxed7 / int
Обычный json_decode для $numberLongarray
Цена после обоих форматов19.90 / 19.90
Незавершённый JSONUnexpectedValueException

Разбор по шагам

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-числа больших значений также ограничены возможностями принимающего языка.

Полная самостоятельная программа и архив
Сохранить различие int32 и Int64 при обмене Extended 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 показывает текст, а не исполняет разметку.

Действия над этими значениями
  1. fromJSON создаёт Document
  2. getIterator возвращает BSON Iterator
  3. foreach получает имя и значение
  4. Разрешены sku/title/quantity/note
  5. NULL сохраняется, internal_token исключён
  6. HTML экранирует значения, JSON следует выбранному договору

Короткое действие

foreach ($document->getIterator() as $name => $value) {
    if (in_array($name, ['sku', 'title', 'quantity', 'note'], true)) {
        $public[$name] = $value;
    }
}
// Для HTML значение отдельно экранируется htmlspecialchars, как в result.html.

Объекты и входные значения подготовлены в полном самостоятельном примере ниже. Здесь выделена операция, которую важно понять сначала.

Что получится

ПолеТипЗначение
skustringMUG-119
titlestring<Кружка>
quantityint2
notenullNULL
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 и максимум один документ. Второй товар не подходит фильтру.

Действия над этими значениями
  1. Записываем два собственных учебных товара
  2. Фильтр _id=101 и active
  3. Projection возвращает четыре поля
  4. typeMap root=bson → Document
  5. Читаем значения и строим локальную копию
  6. Повторный запрос доказывает: копия не изменила базу

Короткое действие

$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 с правилами конкуренции; наличие новой локальной копии не является подтверждением записи.

Полная самостоятельная программа и архив
Прочитать BSON Document из базы только с нужными полямиСамостоятельный пример
<?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-документы
arrayBSON-массивы
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 JSONRelaxed Extended JSON
nullnullnull
booleantrue / falsetrue / 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: stringJSON/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 и типизированная цена; это не обновление записи сервера.

Объяснение и полная самостоятельная программа · Фактическая таблица

Эти фрагменты выделяют вызов из связанных программ; подготовка значений, обработка отказов и полный результат доступны в архиве. Короткий фрагмент не обозначен отдельной запускаемой программой.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.