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

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

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

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

Глава 167 · После первой коллекции; новые BSON-типы разобраны постепенно

MongoDB: время события, ObjectId и внутренний Timestamp

Миллисекунды, местные дни, изменяемые даты, ID из URL, время события, Extended JSON и отдельный смысл BSON Timestamp.

От времени заказа к правильному типу данных

Сервис заказов должен найти запись по ссылке, показать время события человеку и выбрать только нужный календарный день. Для этих действий нужны разные значения: ObjectId отвечает «какой документ», UTCDateTime — «какой момент», а внутренний Timestamp встречается в диагностике MongoDB и обозначает совсем другой формат. Сначала получим понятную таблицу дат, затем последовательно разберём каждую границу.

Момент — одна точка на временной шкале. Зона меняет то, как её называют часы: 00:00 UTC и 03:00 Москвы здесь одно событие. Миллисекунда — тысячная часть секунды. В BSON Date сохраняется число миллисекунд от epoch, а исходная зона не записывается автоматически. Если для бизнеса важно место или правило местного расписания, храните нужную зону отдельно.

Один момент от источника до экрана
  1. Датчик: 2024-01-01 03:00:00.123456+03:00
  2. DateTimeImmutable понимает смещение → UTCDateTime сохраняет 1704067200123 ms
  3. MongoDB хранит BSON Date → запрос возвращает нужные поля
  4. PHP форматирует 00:00:00.123 UTC или 03:00:00.123+03:00
$date = new MongoDB\BSON\UTCDateTime(1704067200123);
echo $date->toDateTimeImmutable()->format('Y-m-d H:i:s.vP');

new создаёт объект. Полное имя MongoDB\BSON\UTCDateTime выбирает тип расширения. Число в скобках — миллисекунды, а не секунды. $date хранит значение в переменной; -> вызывает метод. echo выводит полученную строку 2024-01-01 00:00:00.123+00:00. Эти две строки объясняют одно действие; полный пример ниже ещё записывает его в свою коллекцию и читает обратно.

Предпосылки с начальными объяснениями: переменные, объекты и методы, PHP-даты, первая коллекция и запрос. Здесь значения фиксированы для повторяемого результата; примеры не используют ваши рабочие данные.

Три похожих значения с разным назначением

Что хранитьТипЕдиницы/смыслЧем не является
Время заказаUTCDateTimeМиллисекунды epochНе исходная зона и не полные микросекунды
Идентификатор документаObjectId12 байт; hex для отображенияНе обязательная дата события и не авторизация
Внутренняя BSON-меткаTimestampSeconds+incrementНе дата заказа и не произвольный resume token

Constructor создаёт PHP-значение; запись в коллекцию и серверный запрос выполняются отдельно. Приведение к string или JSON меняет представление для получателя, а не тип уже записанного поля. Поэтому похожая строка ID может находить другой документ, а обычный JSON-массив с $date не становится датой сам собой.

Уже существующие подробные карточки сохраняют точные адреса: ObjectId::__construct, ObjectId::getTimestamp, ObjectId::__toString, UTCDateTime::__construct, UTCDateTime::toDateTimeImmutable и UTCDateTime::__toString.

Запустить программы и увидеть реальные таблицы

Десять ZIP — самостоятельные программы с настоящим обращением к изолированному MongoDB. Нужны PHP CLI 8.4+ x64, ext-mongodb 2.5+, MongoDB 8.0+; стенд проверки PHP 8.5.11/mongodb2.5.5/MongoDB 8.0.34. Каждый архив содержит example.php, mt127-helper.php и README с установкой расширения, выбором CLI php.ini и запуском отдельного mongod. Composer не требуется.

php --ri mongodb
$env:PHPMAN_MONGODB_URI='mongodb://127.0.0.1:27075/?directConnection=true&retryWrites=false'
$env:PHPMAN_MONGODB_DATABASE='php_manual_lab'
php example.php

После запуска откройте result.html: таблица построена из действительно прочитанных данных. result.json содержит те же строки, metrics.json — версии и проверки. Код создаёт случайную учебную коллекцию, удаляет только её в finally и подтверждает отсутствие. На странице доступны сохранённые результаты; браузер читателя не соединяется с учебной базой. Если остановить PHP принудительно, очистка finally может не завершиться.

Сохранить время события с миллисекундами

Датчик прислал время 03:00:00.123456 с поясом +03:00. На общей временной шкале это 00:00 UTC. Сервис должен сохранить момент, показать его оператору и не сделать вид, что база сохранила все шесть знаков дробной секунды. Сразу сравним дату из DateTimeImmutable, целое число миллисекунд и дату до 1970 года.

Входные данные и понятия

Unix epoch — точка отсчёта 1970-01-01 00:00:00 UTC. BSON Date хранит знаковое 64-битное число миллисекунд от неё. Одна секунда содержит 1000 миллисекунд. Значение -1 означает миллисекунду до начала отсчёта, а не ошибку. Часовой пояс исходной строки отдельно в BSON Date не сохраняется.

Путь данных в этом примере
  1. Строка с +03:00 → DateTimeImmutable понимает момент
  2. UTCDateTime → 1704067200123 миллисекунды
  3. BSON Date записан → прочитан как UTCDateTime
  4. Показ UTC: 00:00:00.123; дополнительные 456 микросекунд потеряны

Минимальная запись

$instant = new DateTimeImmutable('2024-01-01T03:00:00.123456+03:00');
$date = new MongoDB\BSON\UTCDateTime($instant);
echo $date->toDateTimeImmutable()->format('Y-m-d H:i:s.vP'); // 2024-01-01 00:00:00.123+00:00

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

IDМиллисекунды epochОтображение UTC
117040672001232024-01-01 00:00:00.123+00:00
2-11969-12-31 23:59:59.999+00:00
317040672001232024-01-01 00:00:00.123+00:00

Почему получился такой результат

new создаёт объект значения. Аргумент DateTimeInterface уже содержит момент и смещение; дополнительное ручное вычитание трёх часов не нужно. Стрелка -> вызывает метод на объекте. toDateTimeImmutable возвращает PHP-дату в UTC; format задаёт её вид. Буква v выводит три знака миллисекунд, P — смещение зоны. В таблице строки 1 и 3 совпали по моменту, хотя исходно заданы разными способами.

Границы и типичные ошибки

Передача time() непосредственно в UTCDateTime перепутает секунды с миллисекундами. Для точности выше миллисекунды храните дополнительное согласованное поле, например исходный timestamp в целых микросекундах или строку нужного формата; нельзя восстановить потерянные разряды одним format. Обязательность времени, допустимый диапазон бизнеса и источник доверенных часов определяет приложение.

Полная самостоятельная программа и архив
Сохранить время события с миллисекундамиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
$input=new DateTimeImmutable('2024-01-01T03:00:00.123456+03:00');
    mt127Insert($manager,$namespace,[['_id'=>1,'at'=>new MongoDB\BSON\UTCDateTime(1704067200123)],
        ['_id'=>2,'at'=>new MongoDB\BSON\UTCDateTime(-1)],['_id'=>3,'at'=>new MongoDB\BSON\UTCDateTime($input)]]);
    $found=mt127Find($manager,$namespace,[],['_id'=>1,'at'=>1]);$rows=[];
    foreach($found as $d){$view=mt127Date($d['at']);$rows[]=[$d['_id'],$view['milliseconds'],$view['utc']];}
    $checks=['three_dates'=>count($found)===3,'milliseconds_preserved'=>(string)$found[0]['at']==='1704067200123',
        'before_epoch'=>(string)$found[1]['at']==='-1','microseconds_truncated'=>$found[2]['at']->toDateTimeImmutable()->format('u')==='123000',
        'same_instant'=>(string)$found[2]['at']===(string)$found[0]['at']];
    $details=['input_microseconds'=>$input->format('Y-m-d H:i:s.uP'),'decoded'=>array_map(fn($d)=>mt127Date($d['at']),$found)];return $rows;
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-utc-milliseconds',['ID', 'Миллисекунды epoch', 'Отображение UTC'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-utc-milliseconds: OK
';
Ожидаемый результат
mongodb127-time-utc-milliseconds: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте исходный момент 2024-01-01T00:00:00.999999Z. Ожидаемая BSON-дата покажет .999, а не следующий момент .000: уменьшение точности не является округлением до ближайшей секунды.

Вопрос из практики: PHP DateTime with TimeZone to MongoDB BSON UTCDateTime. Автор путал исходное смещение строки с переводом момента в именованную зону; преобразование через целые секунды также теряло дробную часть. Здесь момент сначала сохраняется из DateTimeInterface, а нужная зона применяется при отображении. Это постановка проблемы из обсуждения; код и решение здесь составлены заново по актуальному контракту.

Получить только заказы за местный календарный день

Оператор выбрал 1 января в Москве. Ему нужны заказы именно этого календарного дня, а не все документы с последующей фильтрацией в PHP. Входная граница 00:00 Москвы совпадает с 21:00 предыдущего дня UTC. Сформируем обе границы до обращения к базе и получим только ORD-2 и ORD-3.

Входные данные и понятия

Четыре документа специально стоят перед началом, ровно в начале, за миллисекунду до конца и ровно на начале следующего дня. Интервал [start, end) включает начало и исключает конец. Поэтому соседние дни не забирают одну и ту же запись на общей границе.

Путь данных в этом примере
  1. Дата пользователя 2024-01-01 + зона Europe/Moscow
  2. Создать полночь и следующую полночь в этой зоне
  3. Передать BSON Date в $gte и $lt → сервер отбирает строки
  4. Projection/sort/limit → PHP получает два заказа для экрана

Минимальная запись

$zone = new DateTimeZone('Europe/Moscow');
$start = new DateTimeImmutable('2024-01-01 00:00:00', $zone);
$end = $start->modify('+1 day');
$filter = ['created_at'=>['$gte'=>new MongoDB\BSON\UTCDateTime($start), '$lt'=>new MongoDB\BSON\UTCDateTime($end)]];

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

ЗаказМестное время
ORD-22024-01-01 00:00:00.000+03:00
ORD-32024-01-01 23:59:59.999+03:00

Почему получился такой результат

$gte означает «больше или равно», $lt — «меньше». Ключ created_at выбирает поле документа. PHP-массив описывает фильтр, но проверку выполняет MongoDB. В запросе сразу заданы нужные поля, сортировка created_at/_id, лимит и maxTimeMS. Дата выводится в зоне оператора после получения результата; фильтрация не переносится в большой PHP-массив.

Границы и типичные ошибки

Имя зоны нужно явно хранить в настройках пользователя или задачи. Дата без зоны не задаёт однозначный момент. Следующий календарный день вычисляется modify("+1 day") в выбранной зоне: в зонах с DST его длина может отличаться от 86400 секунд. На растущей коллекции индекс по фильтру/порядку проверяют через explain; маленькая фикстура не доказывает производительность. Проверку строки календарной даты формы надо добавить отдельно.

Полная самостоятельная программа и архив
Получить только заказы за местный календарный деньСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
$times=['2023-12-31T20:59:59.999Z','2023-12-31T21:00:00.000Z','2024-01-01T20:59:59.999Z','2024-01-01T21:00:00.000Z'];$docs=[];
    foreach($times as $i=>$text){$docs[]=['_id'=>$i+1,'order'=>'ORD-'.($i+1),'created_at'=>new MongoDB\BSON\UTCDateTime(new DateTimeImmutable($text))];}
    mt127Insert($manager,$namespace,$docs);
    $zone=new DateTimeZone('Europe/Moscow');$start=new DateTimeImmutable('2024-01-01 00:00:00',$zone);$end=$start->modify('+1 day');
    $filter=['created_at'=>['$gte'=>new MongoDB\BSON\UTCDateTime($start),'$lt'=>new MongoDB\BSON\UTCDateTime($end)]];
    $found=mt127Find($manager,$namespace,$filter,['_id'=>1,'order'=>1,'created_at'=>1],['created_at'=>1,'_id'=>1]);
    $checks=['only_required_day'=>array_column($found,'_id')===[2,3],'lower_boundary_utc'=>$start->setTimezone(new DateTimeZone('UTC'))->format('c')==='2023-12-31T21:00:00+00:00',
        'exclusive_upper_bound'=>$end->setTimezone(new DateTimeZone('UTC'))->format('c')==='2024-01-01T21:00:00+00:00'];
    $details=['start'=>$start->format('c'),'exclusive_end'=>$end->format('c'),'filter'=>$filter];
    return array_map(fn($d)=>[$d['order'],$d['created_at']->toDateTimeImmutable()->setTimezone($zone)->format('Y-m-d H:i:s.vP')],$found);
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-local-day-query',['Заказ', 'Местное время'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-local-day-query: OK
';
Ожидаемый результат
mongodb127-time-local-day-query: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Замените зону на America/New_York и выберите день перехода DST. Сравните UTC-границы, не прибавляя фиксированные 24 часа. Для постраничной выдачи добавьте устойчивый порядок и курсор по (created_at,_id), как в разделе индексов.

Вопрос из практики: Trouble querying mongo dates with PHP library. Диапазон находил данные в оболочке, но PHP-запрос с лишним уровнем массива не возвращал нужный результат. Здесь показаны форма фильтра одного дня, включённая нижняя граница и исключённая верхняя, запрос и фактические два заказа. Это постановка проблемы из обсуждения; код и решение здесь составлены заново по актуальному контракту.

Показать одно событие в UTC и местной зоне без изменения базы

Одну дату нужно вывести в журнале UTC и в личном кабинете Москвы. Если два участка кода держат один DateTime, setTimezone изменит общий объект. Покажем различие DateTime и DateTimeImmutable на одном реально прочитанном BSON-значении и проверим, что запись в базе от смены зоны не меняется.

Входные данные и понятия

BSON-значение остаётся 1704067200123. toDateTime создаёт изменяемый DateTime; простое присваивание второй переменной даёт ещё одну ссылку на тот же PHP-объект. У DateTimeImmutable операция смены зоны возвращает другой объект. Обе зоны показывают один момент, а не две разные даты события.

Путь данных в этом примере
  1. MongoDB → один UTCDateTime
  2. toDateTime → общий изменяемый объект → обе переменные видят +03:00
  3. toDateTimeImmutable → исходный UTC и отдельный московский результат
  4. Новое чтение из базы → те же 1704067200123 миллисекунды

Минимальная запись

$utc = $savedDate->toDateTimeImmutable();
$local = $utc->setTimezone(new DateTimeZone('Europe/Moscow'));
// $utc остаётся UTC; $local показывает тот же момент в другой зоне.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

ПредставлениеВремя
DateTime: тот же объект2024-01-01 03:00:00.123+03:00
DateTimeImmutable: исходный2024-01-01 00:00:00.123+00:00
DateTimeImmutable: новый2024-01-01 03:00:00.123+03:00
Новое toDateTime()2024-01-01 00:00:00.123+00:00

Почему получился такой результат

В таблице первая строка относится к изменённому DateTime. Вторая и третья — к исходному immutable и его новому результату. Четвёртая показывает, что повторный toDateTime снова создаёт представление в UTC. Интерфейсный helper mt127Date принимает UTCDateTimeInterface и получает обе формы без привязки к месту, где значение было создано.

Границы и типичные ошибки

Изменение DateTime не обновляет MongoDB. Для настоящего изменения времени нужна явная операция записи. Immutable помогает избежать случайного совместного изменения в PHP, но не обеспечивает авторизацию, валидацию или конкурентную блокировку записи. Не считайте timezone свойством BSON Date: выбранная зона относится к представлению.

Полная самостоятельная программа и архив
Показать одно событие в UTC и местной зоне без изменения базыСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>1,'at'=>new MongoDB\BSON\UTCDateTime(1704067200123)]]);
    $value=mt127Find($manager,$namespace,['_id'=>1],['_id'=>0,'at'=>1])[0]['at'];$summary=mt127Date($value);
    $mutable=$value->toDateTime();$mutableAlias=$mutable;$mutable->setTimezone(new DateTimeZone('Europe/Moscow'));
    $immutable=$value->toDateTimeImmutable();$local=$immutable->setTimezone(new DateTimeZone('Europe/Moscow'));
    $fresh=$value->toDateTime();$loaded=mt127Find($manager,$namespace,['_id'=>1],['_id'=>0,'at'=>1])[0]['at'];
    $checks=['mutable_alias_changed'=>$mutableAlias->format('P')==='+03:00','immutable_original_utc'=>$immutable->format('P')==='+00:00',
        'immutable_copy_local'=>$local->format('P')==='+03:00','fresh_date_utc'=>$fresh->format('P')==='+00:00','stored_milliseconds_unchanged'=>(string)$loaded==='1704067200123'];
    $details=['interface_summary'=>$summary,'same_mutable_object'=>$mutable===$mutableAlias,'different_immutable_object'=>$immutable!==$local];
    return [['DateTime: тот же объект',$mutableAlias->format('Y-m-d H:i:s.vP')],['DateTimeImmutable: исходный',$immutable->format('Y-m-d H:i:s.vP')],['DateTimeImmutable: новый',$local->format('Y-m-d H:i:s.vP')],['Новое toDateTime()',$fresh->format('Y-m-d H:i:s.vP')]];
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-mutable-display',['Представление', 'Время'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-mutable-display: OK
';
Ожидаемый результат
mongodb127-time-mutable-display: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте второй местный вывод в Asia/Tokyo из исходного immutable. UTC и московский результат должны остаться прежними. Затем повторите с одним DateTime и объясните, почему присваивание новой переменной не создало копию объекта.

Передать дату через JSON и восстановить именно BSON Date

Файл обмена должен передать точный момент и после чтения снова дать BSON Date. Обычная ISO-строка удобна для внешнего HTTP API, но сам JSON не знает класса UTCDateTime. Сравним JSON-представление значения с типизированным восстановлением двух дат, включая момент до epoch.

Входные данные и понятия

Extended JSON использует специальные ключи для обозначения BSON-типов. В текущем результате $date содержит $numberLong со строковым числом миллисекунд. jsonSerialize возвращает данные, пригодные для json_encode; это ещё не запись в базу. Document::toCanonicalExtendedJSON формирует выбранный формат обмена целого документа.

Путь данных в этом примере
  1. Прочитанный UTCDateTime → jsonSerialize → JSON для просмотра
  2. Document с полем at → Canonical Extended JSON
  3. json_decode → обычный массив; BSON-тип не восстановлен
  4. Document::fromJSON → get(at) возвращает UTCDateTime с теми же миллисекундами

Минимальная запись

$json = MongoDB\BSON\Document::fromPHP(['at'=>$savedDate])->toCanonicalExtendedJSON();
$restored = MongoDB\BSON\Document::fromJSON($json)->get('at');
// json_decode($json, true) вместо этого дал бы обычный массив с ключами $date/$numberLong.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

IDjsonSerialize → JSONВосстановленный момент
1{"$date":{"$numberLong":"1704067200123"}}2024-01-01 00:00:00.123+00:00
2{"$date":{"$numberLong":"-1"}}1969-12-31 23:59:59.999+00:00

Почему получился такой результат

Готовая таблица показывает компактное представление и восстановленный момент. В раскрываемых промежуточных значениях сохранены полный canonical JSON, результат обычного json_decode и имя восстановленного класса. Данные до 1970 года проходят тот же путь: знак минус является частью значения, а не специальной ошибкой декодера.

Границы и типичные ошибки

Официальное описание jsonSerialize относится к legacy Extended JSON. Наблюдаемое совпадение его формы с canonical для этой даты не даёт такого обещания для всех BSON-типов и версий. Если другой сервис ждёт ISO8601-строку, отдайте явно согласованное поле со строкой; не навязывайте ему $date. Недоверенный JSON требует проверки размера и схемы отдельно.

Полная самостоятельная программа и архив
Передать дату через JSON и восстановить именно BSON DateСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>1,'at'=>new MongoDB\BSON\UTCDateTime(1704067200123)],['_id'=>2,'at'=>new MongoDB\BSON\UTCDateTime(-1)]]);
    $found=mt127Find($manager,$namespace,[],['_id'=>1,'at'=>1]);$rows=[];$ok=true;
    foreach($found as $d){$value=$d['at'];$legacy=mt127Json($value->jsonSerialize());$canonical=MongoDB\BSON\Document::fromPHP(['at'=>$value])->toCanonicalExtendedJSON();
        $plain=json_decode($canonical,true,512,JSON_THROW_ON_ERROR);$restored=MongoDB\BSON\Document::fromJSON($canonical)->get('at');
        $ok=$ok && $restored instanceof MongoDB\BSON\UTCDateTime && (string)$restored===(string)$value && is_array($plain['at']);
        $rows[]=[$d['_id'],$legacy,mt127Date($restored)['utc']];$details['id_'.$d['_id']]=['canonical'=>$canonical,'plain_decode'=>$plain,'restored_type'=>get_debug_type($restored)];}
    $checks=['two_rows'=>count($rows)===2,'restored_dates_and_plain_arrays'=>$ok];return $rows;
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-date-json',['ID', 'jsonSerialize → JSON', 'Восстановленный момент'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-date-json: OK
';
Ожидаемый результат
mongodb127-time-date-json: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Сделайте обычный API-ответ {occurredAt:"...Z"} с миллисекундами, сохранив отдельно canonical-файл для восстановления BSON. Объясните, почему это два осознанных контракта, а не два взаимозаменяемых названия одного формата.

Найти документ по ObjectId из адресной строки

В URL пришёл идентификатор заказа. В базе поле _id имеет тип ObjectId, поэтому строка из URL должна сначала пройти проверку, затем превратиться в ObjectId. Чтобы различие было видно, учебная коллекция содержит одновременно ObjectId и строку с теми же 24 символами: запросы находят разные документы.

Входные данные и понятия

ObjectId состоит из 12 байт; для человека обычно показывают 24 шестнадцатеричных символа. Строка такого вида не меняет BSON-тип сама по себе. mt127ParseId принимает mixed, требует строку из 24 hex-символов и только затем вызывает constructor. Массив с оператором не становится фильтром.

Путь данных в этом примере
  1. Строка URL → проверить тип, длину и hex
  2. new ObjectId → типизированное значение для _id
  3. Query с ObjectId → заказ; Query со string → другая запись
  4. Некорректная строка, массив и null → отказ до запроса

Минимальная запись

$input = '659200800000000000000001';
$id = mt127ParseId($input); // Проверка типа и 24 hex-символов, затем new ObjectId.
$filter = ['_id'=>$id]; // Тип условия соответствует BSON-типу поля.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

Тип условия _idНайденная запись
ObjectIdЗаказ с BSON ObjectId
stringИсторическая запись со строкой

Почему получился такой результат

Одни и те же видимые символы не означают одно и то же значение BSON. Функция преобразования не запускает поиск: её результат используется в фильтре. NULL специально запрещён нашей политикой, потому что штатный constructor без ID создал бы новый идентификатор вместо поиска существующего заказа. Три отвергнутых случая записаны в диагностику.

Границы и типичные ошибки

Правильная форма ID не доказывает существование документа и не даёт права его читать. В реальном многопользовательском сервисе добавьте tenant/user-фильтр и отдельно обработайте пустой результат. Не стройте запрос напрямую из JSON формы. Допустимая структура ID — проверка формата, а не авторизация.

Полная самостоятельная программа и архив
Найти документ по ObjectId из адресной строкиСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
$hex='659200800000000000000001';$id=mt127ParseId($hex);
    mt127Insert($manager,$namespace,[['_id'=>$id,'title'=>'Заказ с BSON ObjectId'],['_id'=>$hex,'title'=>'Историческая запись со строкой']]);
    $typed=mt127Find($manager,$namespace,['_id'=>$id],['_id'=>1,'title'=>1]);$plain=mt127Find($manager,$namespace,['_id'=>$hex],['_id'=>1,'title'=>1]);
    $rejected=0;foreach(['broken',['$ne'=>null],null] as $input){try{mt127ParseId($input);}catch(InvalidArgumentException){$rejected++;}}
    $checks=['one_typed_document'=>count($typed)===1 && $typed[0]['_id'] instanceof MongoDB\BSON\ObjectId,
        'one_string_document'=>count($plain)===1 && is_string($plain[0]['_id']),'invalid_inputs_rejected'=>$rejected===3];
    $details=['typed_id'=>mt127Id($typed[0]['_id']),'typed_json'=>mt127Json($typed[0]['_id']),'invalid_inputs_rejected'=>$rejected];
    return [['ObjectId',$typed[0]['title']],['string',$plain[0]['title']]];
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-typed-id-lookup',['Тип условия _id', 'Найденная запись'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-typed-id-lookup: OK
';
Ожидаемый результат
mongodb127-time-typed-id-lookup: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Запросите другой корректный, но отсутствующий ObjectId. Это должен быть ответ «не найдено», а не ошибка формата. Затем добавьте owner_id к двум записям и покажите, что выбор разрешённой области данных входит в сам запрос.

Вопрос из практики: How to convert string to Object type in Laravel. Строка из запроса не совпадала с BSON ObjectId в поле _id. Наш самостоятельный пример показывает оба типа в одной коллекции, проверку входа и два разных результата; готовый код обсуждения не переносится. Это постановка проблемы из обсуждения; код и решение здесь составлены заново по актуальному контракту.

Отделить время ObjectId от времени заказа

Исторический заказ импортировали позже, чем свежий. Если лента сортирует _id вместо occurred_at, порядок событий может стать неверным. На двух явно заданных ID покажем разницу между секундной частью идентификатора и временем, которое имеет смысл для бизнеса.

Входные данные и понятия

Заказ A имеет ID с датой 1 января и событие 3 января. Заказ B имеет ID с датой 2 января и событие 30 декабря. Значения выбраны вручную, чтобы проверить правило на понятных данных. В настоящем ObjectId первые четыре байта содержат секунды создания ID, но его можно создать заранее или предоставить извне.

Путь данных в этом примере
  1. ObjectId → идентифицирует запись, содержит секундный компонент
  2. occurred_at → хранит явное время события с миллисекундами
  3. Сортировка _id → A, B
  4. Сортировка occurred_at,_id → B, A

Минимальная запись

$generatedSeconds = $document['_id']->getTimestamp();
$eventInstant = $document['occurred_at'];
// Для ленты событий запрос сортирует occurred_at, затем _id как дополнительный ключ.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

Заказ по _idСекундная часть ObjectId, UTCoccurred_at, UTC
A2024-01-01 00:00:002024-01-03 09:00:00
B2024-01-02 00:00:002023-12-30 10:00:00

Почему получился такой результат

getTimestamp возвращает секунды epoch, а не BSON Date и не время подтверждения записи сервером. gmdate в таблице только форматирует эти секунды как UTC. Отдельный запрос сортирует по полю occurred_at; в диагностике виден другой порядок. _id добавлен вторым ключом для устойчивого порядка одинаковых дат.

Границы и типичные ошибки

ObjectId не гарантирует строгий глобальный порядок создания: точность компонента одна секунда, часы клиентов различаются, значения могут формироваться разными процессами или передаваться вручную. Не измеряйте им длительность заказа и не доказывайте время оплаты. Если важны created_at, paid_at, received_at — храните отдельные поля с понятным источником.

Полная самостоятельная программа и архив
Отделить время ObjectId от времени заказаСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>new MongoDB\BSON\ObjectId('659200800000000000000001'),'order'=>'A','occurred_at'=>new MongoDB\BSON\UTCDateTime(new DateTimeImmutable('2024-01-03T09:00:00Z'))],
        ['_id'=>new MongoDB\BSON\ObjectId('659352000000000000000001'),'order'=>'B','occurred_at'=>new MongoDB\BSON\UTCDateTime(new DateTimeImmutable('2023-12-30T10:00:00Z'))]]);
    $byId=mt127Find($manager,$namespace,[],['_id'=>1,'order'=>1,'occurred_at'=>1]);
    $byEvent=mt127Find($manager,$namespace,[],['_id'=>1,'order'=>1,'occurred_at'=>1],['occurred_at'=>1,'_id'=>1]);
    $checks=['id_order'=>array_column($byId,'order')===['A','B'],'event_order'=>array_column($byEvent,'order')===['B','A'],
        'id_seconds'=>$byId[0]['_id']->getTimestamp()===1704067200];$details=['ordered_by_event'=>array_column($byEvent,'order'),'id_contract'=>mt127Id($byId[0]['_id'])];
    return array_map(fn($d)=>[$d['order'],gmdate('Y-m-d H:i:s',$d['_id']->getTimestamp()),$d['occurred_at']->toDateTimeImmutable()->format('Y-m-d H:i:s')],$byId);
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-id-business-time',['Заказ по _id', 'Секундная часть ObjectId, UTC', 'occurred_at, UTC'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-id-business-time: OK
';
Ожидаемый результат
mongodb127-time-id-business-time: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте заказ C с тем же occurred_at, что у B, но другим ObjectId. Проверьте устойчивость порядка по двум ключам. Затем обсудите, какое время нужно для отчёта: момент события источника или момент его приёма вашим сервисом.

Отдать ID клиенту и сохранить тип в Extended JSON

Браузеру нужна строка ID для следующего запроса, а файлу миграции нужен сохранённый BSON-тип. Это разные договорённости. На одном заказе подготовим обычное поле id и Extended JSON, восстановим ObjectId и реально найдём документ по восстановленному значению.

Входные данные и понятия

(string)$id даёт hex для ссылки, формы или обычного API. jsonSerialize даёт данные с ключом $oid. json_decode понимает только JSON и возвращает вложенный массив. Document::fromJSON понимает Extended JSON и создаёт BSON ObjectId.

Путь данных в этом примере
  1. Из базы получен настоящий ObjectId
  2. Для HTTP-клиента → id как hex-строка
  3. Для типизированного обмена → $oid в документе
  4. BSON-декодирование → восстановленный ObjectId → найден тот же заказ

Минимальная запись

$api = ['id'=>(string)$id]; // Контракт обычного HTTP API: строковый идентификатор.
$bsonJson = MongoDB\BSON\Document::fromPHP(['_id'=>$id])->toCanonicalExtendedJSON();
// Контракт типизированного обмена: $oid, восстанавливаемый BSON-декодером.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

НазначениеРезультат
Обычный API: поле id{"id":"659200800000000000000001"}
Extended JSON значения{"$oid":"659200800000000000000001"}
Тип после Document::fromJSONMongoDB\BSON\ObjectId
Повторный запросЗаказ A

Почему получился такой результат

В таблице рядом видны оба JSON-контракта. Запись типа после fromJSON подтверждает, что восстановилась не stdClass с похожими полями. Повторный запрос не использует строковый _id: в фильтр передан восстановленный объект. mt127Id показывает отдельные hex и секунды через ObjectIdInterface.

Границы и типичные ошибки

Нельзя вызывать __toString на любом stdClass, полученном из json_decode: это не ObjectId. И нельзя считать наличие ключа $oid подтверждением доверенного содержимого файла. Выбирайте JSON-декодер по формату, проверяйте схему и ограничения входа; ошибку восстановления не подменяйте новым случайным ID.

Полная самостоятельная программа и архив
Отдать ID клиенту и сохранить тип в Extended JSONСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>new MongoDB\BSON\ObjectId('659200800000000000000001'),'title'=>'Заказ A']]);
    $id=mt127Find($manager,$namespace,[],['_id'=>1])[0]['_id'];$view=mt127Id($id);
    $json=mt127Json($id->jsonSerialize());$canonical=MongoDB\BSON\Document::fromPHP(['_id'=>$id])->toCanonicalExtendedJSON();
    $plain=json_decode($canonical,true,512,JSON_THROW_ON_ERROR);$restored=MongoDB\BSON\Document::fromJSON($canonical)->get('_id');
    $roundtrip=mt127Find($manager,$namespace,['_id'=>$restored],['_id'=>1,'title'=>1]);
    $checks=['hex_string'=>$view['hex']==='659200800000000000000001','plain_array_not_bson'=>is_array($plain['_id']),
        'native_restored'=>$restored instanceof MongoDB\BSON\ObjectId,'restored_lookup'=>count($roundtrip)===1 && $roundtrip[0]['title']==='Заказ A'];
    $details=['canonical'=>$canonical,'plain_decode'=>$plain,'interface_summary'=>$view,'restored_interface'=>mt127Id($restored)];
    return [['Обычный API: поле id',mt127Json(['id'=>(string)$id])],['Extended JSON значения',$json],['Тип после Document::fromJSON',get_debug_type($restored)],['Повторный запрос',$roundtrip[0]['title']]];
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-id-json',['Назначение', 'Результат'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-id-json: OK
';
Ожидаемый результат
mongodb127-time-id-json: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Отправьте поле id из первой строки обратно в mt127ParseId и выполните запрос. Затем восстановите canonical документ через fromJSON. Оба маршрута могут найти запись, но у каждого явный формат и отдельный шаг преобразования.

Прочитать две части внутреннего BSON Timestamp

При разборе диагностических документов MongoDB можно встретить Timestamp и ошибочно принять его за дату заказа. Сначала прочитаем его две части и посмотрим серверный порядок учебных меток. Ни одна из меток не выдана системой репликации; мы исследуем формат в отдельной обычной коллекции.

Входные данные и понятия

BSON Timestamp содержит два unsigned 32-bit компонента: секунды epoch и порядковую часть increment. Порядковая часть различает операции внутри секунды, это не миллисекунды и не доля секунды. Constructor принимает сначала increment, затем timestamp; отображение PHP [increment:timestamp] следует этому порядку.

Путь данных в этом примере
  1. Заданы три учебные пары: (8,t), (7,t), (1,t+1)
  2. Сохранение BSON Timestamp → отдельный тип поля marker
  3. Сортировка marker базой → сперва секунды, затем increment
  4. Getter возвращает компоненты; подпись [7:t] не используется как дата

Минимальная запись

$marker = new MongoDB\BSON\Timestamp(7, 1704067200);
echo $marker->getTimestamp(); // 1704067200 секунд
echo $marker->getIncrement(); // 7: порядковая часть, не 7 миллисекунд

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

IDСекундыПорядковая частьСтрока PHP
217040672007[7:1704067200]
117040672008[8:1704067200]
317040672011[1:1704067201]

Почему получился такой результат

Результат ID 2,1,3 показывает, что 1 следующей секунды идёт после 8 предыдущей. getTimestamp и getIncrement возвращают int на нашем x64-стенде. Типизированный helper mt127Marker принимает TimestampInterface и не пытается разбивать строку по двоеточию. Текущая задача — корректно показать внутреннее значение, а не заменить им пользовательское время.

Границы и типичные ошибки

Для времени события нужен UTCDateTime. Конструирование Timestamp не создаёт настоящую позицию oplog, resume token, причинную связь или подтверждённый clusterTime. Нельзя подставлять произвольную учебную пару в управление сессиями. На 32-битном PHP большие unsigned компоненты могут выглядеть отрицательными; документация предлагает sprintf("%u", ...), а этот опыт явно требует x64.

Полная самостоятельная программа и архив
Прочитать две части внутреннего BSON TimestampСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>1,'marker'=>new MongoDB\BSON\Timestamp(8,1704067200)],
        ['_id'=>2,'marker'=>new MongoDB\BSON\Timestamp(7,1704067200)],['_id'=>3,'marker'=>new MongoDB\BSON\Timestamp(1,1704067201)]]);
    $found=mt127Find($manager,$namespace,[],['_id'=>1,'marker'=>1],['marker'=>1]);$rows=[];
    foreach($found as $d){$v=mt127Marker($d['marker']);$rows[]=[$d['_id'],$v['seconds'],$v['increment'],$v['display']];}
    $checks=['timestamp_order'=>array_column($found,'_id')===[2,1,3],'seconds_not_milliseconds'=>$found[0]['marker']->getTimestamp()===1704067200,
        'increment_not_fraction'=>$found[0]['marker']->getIncrement()===7];$details=['first_contract'=>mt127Marker($found[0]['marker']),'json_value'=>mt127Json($found[0]['marker']),'purpose'=>'Synthetic inspection only; no oplog/session changes'];return $rows;
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-timestamp-parts',['ID', 'Секунды', 'Порядковая часть', 'Строка PHP'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-timestamp-parts: OK
';
Ожидаемый результат
mongodb127-time-timestamp-parts: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте Timestamp(9,t) и предскажите место между (8,t) и (1,t+1). Затем попробуйте выразить 123 миллисекунды после полуночи: объясните, почему increment=123 не является подходящей моделью и нужно отдельное UTCDateTime.

Перенести диагностическую метку без потери компонентов

В выгрузке диагностического документа есть и внутренняя метка marker, и прикладной event_at. Если превратить всё в одну строку «timestamp», смысл полей потеряется. Сохраним оба BSON-типа через Extended JSON и сравним компоненты после восстановления.

Входные данные и понятия

marker задан парой increment=7,seconds=1704067200. event_at задан 1704067200123 миллисекундами. Специальные ключи $timestamp и $date передают разные типы. У Timestamp JSON содержит t и i; строка PHP показывает обратный порядок increment:seconds.

Путь данных в этом примере
  1. Один документ → marker: Timestamp и event_at: UTCDateTime
  2. Canonical JSON содержит разные ключи типов
  3. Document::fromJSON восстанавливает два разных класса
  4. Проверка seconds/increment отдельно; проверка миллисекунд даты отдельно

Минимальная запись

$json = MongoDB\BSON\Document::fromPHP(['marker'=>$marker,'event_at'=>$date])->toCanonicalExtendedJSON();
$restored = MongoDB\BSON\Document::fromJSON($json);
// $timestamp и $date восстанавливаются в разные BSON-классы.

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

ПолеJSON значенияПосле восстановления
marker{"$timestamp":{"t":1704067200,"i":7}}[7:1704067200]
event_at{"$date":{"$numberLong":"1704067200123"}}2024-01-01 00:00:00.123+00:00

Почему получился такой результат

В результате маркер остаётся [7:1704067200], а дата — 00:00:00.123 UTC. Сравниваются значения компонентов, а не идентичность PHP-объектов. jsonSerialize вызывается явно для просмотра, целый документ экспортируется через Document API. Форматирование времени относится только к event_at.

Границы и типичные ошибки

Даже точное восстановление учебного Timestamp не делает его настоящей серверной меткой. Этот код не обращается к oplog, не продвигает время сессии и не подписывает clusterTime. Обмен диагностикой и управление консистентностью — разные задачи. json_decode можно использовать для просмотра ключей, но не для автоматического восстановления BSON-классов.

Полная самостоятельная программа и архив
Перенести диагностическую метку без потери компонентовСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
mt127Insert($manager,$namespace,[['_id'=>1,'marker'=>new MongoDB\BSON\Timestamp(7,1704067200),'event_at'=>new MongoDB\BSON\UTCDateTime(1704067200123)]]);
    $doc=mt127Find($manager,$namespace,['_id'=>1],['_id'=>0,'marker'=>1,'event_at'=>1])[0];$marker=$doc['marker'];
    $canonical=MongoDB\BSON\Document::fromPHP($doc)->toCanonicalExtendedJSON();$restored=MongoDB\BSON\Document::fromJSON($canonical);
    $again=$restored->get('marker');$date=$restored->get('event_at');$a=mt127Marker($marker);$b=mt127Marker($again);
    $checks=['components_preserved'=>$a===$b,'separate_timestamp_type'=>$again instanceof MongoDB\BSON\Timestamp,
        'separate_date_type'=>$date instanceof MongoDB\BSON\UTCDateTime,'date_ms_preserved'=>(string)$date==='1704067200123'];
    $details=['canonical'=>$canonical,'readback_contract'=>$b];
    return [['marker',mt127Json($marker->jsonSerialize()),(string)$again],['event_at',mt127Json($doc['event_at']->jsonSerialize()),mt127Date($date)['utc']]];
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-timestamp-roundtrip',['Поле', 'JSON значения', 'После восстановления'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-timestamp-roundtrip: OK
';
Ожидаемый результат
mongodb127-time-timestamp-roundtrip: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте второй event_at, оставив marker прежним, и объясните, почему equality маркера не доказывает равенство событий. Для внешнего API опишите оба поля раздельно или отдавайте только действительно нужную клиенту дату.

Проверить границы компонентов и не скрывать ошибки данных

Импорт диагностических меток должен заметно отвергать неправильные компоненты. Если вместо отказа молча обрезать число или привести отрицательное к unsigned, получатся другие данные. Проверим границы каждого компонента и сохраним понятный журнал допустимых и отвергнутых случаев.

Входные данные и понятия

Оба компонента имеют диапазон 0..4294967295. На x64 PHP эти значения помещаются в int. В наборе два допустимых значения и четыре случая за пределами: отрицательный increment, отрицательные seconds и превышение максимума каждого компонента. В таблице ошибка хранится отдельно от значения marker.

Путь данных в этом примере
  1. Фиксированный набор входных пар → constructor
  2. Допустимая пара → Timestamp без изменения данных
  3. Недопустимая пара → ожидаемый InvalidArgumentException
  4. Журнал записан и прочитан из своей коллекции; четыре отказа видны явно

Минимальная запись

try {
    $marker = new MongoDB\BSON\Timestamp(-1, 1704067200);
} catch (MongoDB\Driver\Exception\InvalidArgumentException $error) {
    // Ожидаемый отказ: компонент не является unsigned 32-bit числом.
}

Этот фрагмент выделяет текущий шаг. Полная программа содержит данные, настоящий запрос, проверки и очистку собственной коллекции.

Результат

increment входseconds входРезультат созданияПредставление
71704067200accepted[7:1704067200]
42949672954294967295accepted[4294967295:4294967295]
-11InvalidArgumentException—
1-1InvalidArgumentException—
42949672961InvalidArgumentException—
14294967296InvalidArgumentException—

Почему получился такой результат

Ловится только ожидаемое исключение constructor; сетевые и другие ошибки не скрываются. Максимальные значения после чтения снова равны 4294967295. В сохранённых отказах marker=null, а не произвольная запасная дата. Вывод чисел как строк в таблице намеренно избегает ограничений JavaScript-клиента при дальнейшем развитии формата.

Границы и типичные ошибки

Граница технического типа не является допустимым диапазоном предметной модели. Для внешнего ввода дополнительно проверяйте тип, форму числа и нужный бизнес-диапазон до constructor. Пара Timestamp(0,0) не служит универсальным признаком «пустой даты»: этот опыт её не вставляет. Отсутствие значения выражайте отдельно, согласно схеме приложения.

Полная самостоятельная программа и архив
Проверить границы компонентов и не скрывать ошибки данныхСамостоятельный пример
<?php
declare(strict_types=1);
require __DIR__.'/mt127-helper.php';
[$uri,$db]=mt127Config();
$manager=new MongoDB\Driver\Manager($uri,['connectTimeoutMS'=>1000,'serverSelectionTimeoutMS'=>1500,'socketTimeoutMS'=>2000,'retryReads'=>false]);
$runtime=['php'=>PHP_VERSION,'extension'=>phpversion('mongodb'),'server'=>mt127Command($manager,$db,['buildInfo'=>1])[0]['version'],'execution'=>'database'];
$checks=[];$details=[];
$rows=mt127WithCollection($manager,$db,function(string $namespace,string $collection) use($manager,$db,&$checks,&$details): array {
$cases=[[7,1704067200],[4294967295,4294967295],[-1,1],[1,-1],[4294967296,1],[1,4294967296]];$docs=[];$expected=[];
    foreach($cases as $index=>[$increment,$seconds]){try{$marker=new MongoDB\BSON\Timestamp($increment,$seconds);$status='accepted';$display=(string)$marker;}
        catch(MongoDB\Driver\Exception\InvalidArgumentException){$marker=null;$status='InvalidArgumentException';$display='—';}
        $docs[]=['_id'=>$index+1,'increment_input'=>$increment,'seconds_input'=>$seconds,'status'=>$status,'marker'=>$marker,'display'=>$display];$expected[]=$status;}
    mt127Insert($manager,$namespace,$docs);$found=mt127Find($manager,$namespace,[],['_id'=>1,'increment_input'=>1,'seconds_input'=>1,'status'=>1,'marker'=>1,'display'=>1]);
    $checks=['two_valid_four_rejected'=>$expected===['accepted','accepted','InvalidArgumentException','InvalidArgumentException','InvalidArgumentException','InvalidArgumentException'],
        'maximum_unsigned_components'=>$found[1]['marker']->getIncrement()===4294967295 && $found[1]['marker']->getTimestamp()===4294967295,
        'persisted_outcomes'=>array_column($found,'status')===$expected];
    $details=['maximum_contract'=>mt127Marker($found[1]['marker']),'runtime_bits'=>PHP_INT_SIZE*8];
    return array_map(fn($d)=>[(string)$d['increment_input'],(string)$d['seconds_input'],$d['status'],$d['display']],$found);
});
$checks['owned_collection_removed']=true;
mt127Report('mongodb127-time-timestamp-bounds',['increment вход', 'seconds вход', 'Результат создания', 'Представление'],$rows,$checks,$runtime,$details);
echo 'mongodb127-time-timestamp-bounds: OK
';
Ожидаемый результат
mongodb127-time-timestamp-bounds: OK

Реальная запись и чтение в отдельной локальной MongoDB; даты и ID фиксированы. HTML/JSON показывают фактические данные. Поддерживающий helper и инструкция находятся в ZIP.

Открыть фактическую таблицу и промежуточные значения · Данные результата JSON

Упражнение с направлением решения. Добавьте правило приложения, допускающее только уже известный диапазон секунд, и отдельно показывайте отказ политики и отказ BSON constructor. Не исправляйте переполнение через float или умножение без проверки диапазона.

Классы, интерфейсы и методы времени и идентификаторов

Новые карточки раскрывают 22 ранее отсутствовавших контракта. Ранее описанные методы ObjectId constructor/getTimestamp/__toString и UTCDateTime constructor/toDateTimeImmutable/__toString сохраняют свои адреса в базовой главе BSON. Этот пакет дополняет справочник и не является заявлением о полноте всего MongoDB.

Класс или методЗадача
MongoDB\BSON\ObjectIdИдентифицировать документ BSON-значением и отличать его от строкового адреса.
MongoDB\BSON\ObjectIdInterfaceПринять идентификатор в своей функции с явным контрактом двух операций.
MongoDB\BSON\ObjectId::jsonSerializeПредставить ObjectId в JSON с обозначением BSON-типа.
MongoDB\BSON\ObjectIdInterface::getTimestampПрочитать часть идентификатора через общий тип ObjectIdInterface.
MongoDB\BSON\ObjectIdInterface::__toStringПрочитать часть идентификатора через общий тип ObjectIdInterface.
MongoDB\BSON\UTCDateTimeХранить момент события в BSON Date и фильтровать нужный диапазон на сервере.
MongoDB\BSON\UTCDateTimeInterfaceНаписать функцию отображения даты, зависящую от операций времени, а не места чтения документа.
MongoDB\BSON\UTCDateTime::toDateTimeПолучить изменяемую PHP-дату в UTC для форматирования или календарных операций.
MongoDB\BSON\UTCDateTime::jsonSerializeПолучить данные для JSON-представления даты с обозначением BSON-типа.
MongoDB\BSON\UTCDateTimeInterface::toDateTimeПолучить представление даты через тип UTCDateTimeInterface.
MongoDB\BSON\UTCDateTimeInterface::toDateTimeImmutableПолучить представление даты через тип UTCDateTimeInterface.
MongoDB\BSON\UTCDateTimeInterface::__toStringПолучить представление даты через тип UTCDateTimeInterface.
MongoDB\BSON\TimestampКорректно читать внутреннюю BSON-метку и не путать её со временем прикладного события.
MongoDB\BSON\TimestampInterfaceОписать тип параметра диагностической функции, читающей части BSON Timestamp.
MongoDB\BSON\Timestamp::__constructСоздать BSON-значение из двух явно названных компонентов для известного формата данных.
MongoDB\BSON\Timestamp::getIncrementПрочитать порядковую часть BSON Timestamp.
MongoDB\BSON\TimestampInterface::getIncrementПрочитать порядковую часть BSON Timestamp.
MongoDB\BSON\Timestamp::getTimestampПрочитать секундную часть BSON Timestamp.
MongoDB\BSON\TimestampInterface::getTimestampПрочитать секундную часть BSON Timestamp.
MongoDB\BSON\Timestamp::jsonSerializeПоказать обе части Timestamp в типизированном JSON-представлении.
MongoDB\BSON\Timestamp::__toStringПолучить подпись внутренней метки для диагностического экрана.
MongoDB\BSON\TimestampInterface::__toStringПолучить подпись внутренней метки для диагностического экрана.

От явных типов к понятному запросу и обмену

Сначала определите, что означает поле: идентификатор, момент события или внутренний технический маркер. Дальше согласуйте тип хранения, единицы и формат обмена. Фильтрацию нужного дня и сортировку выполняйте запросом, а PHP отдавайте только нужную страницу и нужные поля. Отдельно задавайте источник времени, зону пользователя и правила доступа.

Далее: точные числа для интеграций и расчётов, Document и Extended JSON, индексы и постраничная выдача, транзакции. Для полного перечня API используйте справочник функций и классов.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

MongoDB\BSON\ObjectIdИдентифицировать документ BSON-значением и отличать его от строкового адреса.

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно. В 1.3.0 историческое написание ObjectID изменено на ObjectId. · mongodb

final class MongoDB\BSON\ObjectId implements ObjectIdInterface, Type, JsonSerializable, Stringable

Параметры и вызов

Создание: __construct(?string $id = null). Без ID генерируется новое значение; с ID ожидается 24 hex-символа. Собственные методы: getTimestamp(): int, jsonSerialize(): mixed, __toString(): string. Вопросы constructor/getTimestamp/__toString подробно раскрыты в ранее существующих карточках BSON values.

Возвращаемое значение

Объект 12-байтного ObjectId: 4 байта секунд epoch, 5 байт случайной части, 3 байта счётчика. При вставке документа без _id драйвер обычно создаёт ObjectId. _id должен быть уникальным в коллекции; повторная вставка того же ID — уже ошибка записи, а не ошибка создания PHP-объекта.

Ошибки и границы

Неверная строка constructor вызывает MongoDB\Driver\Exception\InvalidArgumentException. Валидный ID может отсутствовать в базе. Ошибку формата, пустую выборку и duplicate key обрабатывают на разных шагах.

Секундная часть полезна для диагностики, но не заменяет время события. Порядок _id приблизителен для времени создания: часы, процессы, одна секунда точности и явно заданные значения мешают считать его строгим порядком.

Версии

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно. В 1.3.0 историческое написание ObjectID изменено на ObjectId.

Найти BSON-идентификатор из URL

$filter = ['_id'=>mt127ParseId($input)];

Полный пример показывает два разных документа: один с ObjectId, другой со строкой тех же символов.

Полная программа, данные и результат

Показать ID отдельно от времени события

$identity = mt127Id($document['_id']);

Helper получает hex и секунды через интерфейс; отдельный occurred_at определяет порядок ленты.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\ObjectIdInterfaceПринять идентификатор в своей функции с явным контрактом двух операций.

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. · mongodb

interface MongoDB\BSON\ObjectIdInterface { public function getTimestamp(): int; public function __toString(): string; }

Параметры и вызов

Интерфейс применяют как тип параметра, свойства или результата. Его реализует ObjectId. Два метода без аргументов: getTimestamp(): int и __toString(): string.

Возвращаемое значение

Контракт чтения секунд и hex-представления. Интерфейс не является constructor, не создаёт объект и сам по себе не обещает BSON-кодирование произвольной пользовательской реализации.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Type hint помогает описать зависимость функции, но не подтверждает достоверность времени, существование документа или права чтения. Примеры используют настоящий ObjectId до/после базы.

Версии

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны.

Найти BSON-идентификатор из URL

$filter = ['_id'=>mt127ParseId($input)];

Полный пример показывает два разных документа: один с ObjectId, другой со строкой тех же символов.

Полная программа, данные и результат

Показать ID отдельно от времени события

$identity = mt127Id($document['_id']);

Helper получает hex и секунды через интерфейс; отдельный occurred_at определяет порядок ленты.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\ObjectId::jsonSerializeПредставить ObjectId в JSON с обозначением BSON-типа.

С ext-mongodb 1.2.0. Официальное описание относит формат к driver-specific legacy Extended JSON; для современного документа здесь явно вызывается Document::toCanonicalExtendedJSON. · mongodb

final public function MongoDB\BSON\ObjectId::jsonSerialize(): mixed

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Данные для json_encode и Extended JSON значения; в текущем примере объект с $oid и hex-строкой. Контракт mixed не следует подменять обещанием PHP-массива во всех версиях. Это не результат поиска документа.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

Обычный HTTP API может выбрать строковое поле id. В JSON для восстановления BSON нужен согласованный типизированный формат и BSON-декодер, а не автоматическое ожидание, что json_decode создаст ObjectId.

Версии

С ext-mongodb 1.2.0. Официальное описание относит формат к driver-specific legacy Extended JSON; для современного документа здесь явно вызывается Document::toCanonicalExtendedJSON.

Сравнить API-строку и типизированный JSON

$api = ['id'=>(string)$id];
$typed = json_encode($id->jsonSerialize(), JSON_THROW_ON_ERROR);

Таблица отдельно показывает id и $oid, затем восстановленный класс и повторно найденный заказ.

Полная программа, данные и результат

Показать тип введённого идентификатора

$debug = json_encode($typed[0]['_id'], JSON_THROW_ON_ERROR);

Типизированный ObjectId из полного примера реализует JsonSerializable; JSON-обёртка служит диагностике и не подменяет BSON-фильтр.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\ObjectIdInterface::getTimestampПрочитать часть идентификатора через общий тип ObjectIdInterface.

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. · mongodb

abstract public function MongoDB\BSON\ObjectIdInterface::getTimestamp(): int

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Секундный компонент ObjectId; для настоящего ObjectId это первые четыре байта. Это не миллисекунды, не verified created_at и не момент вставки.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Интерфейс задаёт результат операции, а не доверие к источнику ID. Конкретное BSON-значение и обычная строка остаются разными типами.

Версии

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны.

Сопоставить техническое время и событие

$seconds = $document['_id']->getTimestamp();

Сортировки _id и occurred_at дают разный порядок A/B.

Полная программа, данные и результат

Проверить контракт восстановленного ID

$metadata = mt127Id($restored);

Helper поддерживает отдельное чтение секунд и hex вместо разбора Extended JSON как объекта.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\ObjectIdInterface::__toStringПрочитать часть идентификатора через общий тип ObjectIdInterface.

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. · mongodb

abstract public function MongoDB\BSON\ObjectIdInterface::__toString(): string

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Hex-представление ObjectId. Для реального класса это строка из 24 шестнадцатеричных символов, удобная для согласованного внешнего API.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Интерфейс задаёт результат операции, а не доверие к источнику ID. Конкретное BSON-значение и обычная строка остаются разными типами.

Версии

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны.

Подпись ID найденного документа

$hex = (string) $document['_id'];

Подпись не изменяет тип сохранённого поля: фильтр со строкой находит другую запись.

Полная программа, данные и результат

Обычное строковое поле HTTP API

$api = ['id'=>(string)$id];

Клиент получает строку; при обратном запросе приложение проверяет её и создаёт ObjectId.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTimeХранить момент события в BSON Date и фильтровать нужный диапазон на сервере.

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно. · mongodb

final class MongoDB\BSON\UTCDateTime implements UTCDateTimeInterface, Type, JsonSerializable, Stringable

Параметры и вызов

__construct(int|MongoDB\BSON\Int64|DateTimeInterface|null $milliseconds = null). Число — миллисекунды epoch; DateTimeInterface задаёт момент; null/без аргумента — текущее время. Методы: jsonSerialize(): mixed, toDateTime(): DateTime, toDateTimeImmutable(): DateTimeImmutable, __toString(): string. Immutable-конверсия введена в 2.0.0.

Возвращаемое значение

BSON Date со знаковым 64-битным количеством миллисекунд. Отрицательные значения допустимы. Исходная timezone и субмиллисекундная точность не хранятся. Чтение возвращает типизированное значение, которое можно отдельно форматировать для пользователя.

Ошибки и границы

При ошибке разбора аргумента constructor документация указывает MongoDB\Driver\Exception\InvalidArgumentException. С ext-mongodb 2.0 constructor больше не принимает string и float. Int64 принят с 1.20.0; необязательный аргумент и DateTimeInterface — с 1.2.0. Сетевые ошибки относятся к записи/чтению, а не объекту даты.

Не умножайте DateTimeInterface на 1000: constructor уже понимает его момент. И не передавайте секунды в числовой аргумент. Для 32-bit чисел за пределами PHP int используйте поддерживаемый BSON Int64; наши программы явно x64.

Версии

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно.

Сохранить долю секунды и дату до epoch

$value = new MongoDB\BSON\UTCDateTime($dateTime);

Таблица показывает точность .123 и -1 ms; исходные микросекунды не объявляются сохранёнными.

Полная программа, данные и результат

Фильтр календарного дня

$filter=['created_at'=>['$gte'=>new MongoDB\BSON\UTCDateTime($start),'$lt'=>new MongoDB\BSON\UTCDateTime($end)]];

Две локальные границы становятся моментами UTC до передачи запроса.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTimeInterfaceНаписать функцию отображения даты, зависящую от операций времени, а не места чтения документа.

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. Метод toDateTimeImmutable введён в 2.0.0. · mongodb

interface MongoDB\BSON\UTCDateTimeInterface { public function toDateTime(): DateTime; public function toDateTimeImmutable(): DateTimeImmutable; public function __toString(): string; }

Параметры и вызов

Тип для параметров, свойств и результатов. Три метода без аргументов: toDateTime, toDateTimeImmutable и __toString. Настоящий UTCDateTime реализует этот интерфейс.

Возвращаемое значение

Контракт изменяемого/неизменяемого PHP-представления UTC и строкового представления BSON-даты. Интерфейс не хранит значение самостоятельно, не предоставляет constructor и не является разрешением на запись произвольного собственного класса в BSON.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Нельзя считать все объекты, имеющие похожее поле date, реализациями интерфейса. Type hint проверяет тип; семантическую достоверность времени и нужную зону приложения задают отдельно.

Версии

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. Метод toDateTimeImmutable введён в 2.0.0.

Прочитать сохранённый момент

$view = mt127Date($document['at']);

Один helper получает миллисекунды и два UTC-представления. Дата -1 ms остаётся датой до epoch.

Полная программа, данные и результат

Показать дату в двух зонах

$utc = $value->toDateTimeImmutable();
$local = $utc->setTimezone(new DateTimeZone('Europe/Moscow'));

Изменение представления не изменяет BSON-значение и не выполняет update в базе.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTime::toDateTimeПолучить изменяемую PHP-дату в UTC для форматирования или календарных операций.

С ext-mongodb 1.0.0. · mongodb

final public function MongoDB\BSON\UTCDateTime::toDateTime(): DateTime

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Новый DateTime, представляющий тот же момент в UTC. DateTime можно изменять; изменение этого объекта не изменяет исходный UTCDateTime и документ MongoDB. Миллисекунды отображаются в микросекундном поле с последними тремя нулями.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

Две PHP-переменные после обычного присваивания могут ссылаться на один DateTime. Если смена зоны не должна затрагивать другие участки кода, используйте независимую копию либо toDateTimeImmutable.

Версии

С ext-mongodb 1.0.0.

Увидеть совместное изменение DateTime

$date=$value->toDateTime();
$alias=$date;
$date->setTimezone(new DateTimeZone('Europe/Moscow'));

Alias тоже показывает +03:00, но повторное чтение BSON даёт прежние миллисекунды.

Полная программа, данные и результат

Форматировать прочитанную дату в общем helper

$utc = $value->toDateTime()->format('Y-m-d H:i:s.vP');

mt127Date сопоставляет mutable и immutable UTC, включая -1 миллисекунду.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTime::jsonSerializeПолучить данные для JSON-представления даты с обозначением BSON-типа.

С ext-mongodb 1.2.0. Официальный контракт говорит о legacy Extended JSON; для явного canonical обмена целыми документами здесь применяется текущий Document API. · mongodb

final public function MongoDB\BSON\UTCDateTime::jsonSerialize(): mixed

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Данные, которые json_encode превращает в Extended JSON. На текущем стенде это $date с вложенным $numberLong, содержащим строку миллисекунд. Метод не возвращает готовый DateTime или строку ISO8601.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

Не гарантируйте, что jsonSerialize всех BSON-типов соответствует canonical. Совпадение формы конкретной даты проверяется как наблюдение; формат обмена должен быть явным.

Версии

С ext-mongodb 1.2.0. Официальный контракт говорит о legacy Extended JSON; для явного canonical обмена целыми документами здесь применяется текущий Document API.

Восстановить обычную и отрицательную дату

$view=json_encode($date->jsonSerialize(),JSON_THROW_ON_ERROR);

Рядом показаны canonical-файл и результат fromJSON, сохраняющий -1 или 1704067200123.

Полная программа, данные и результат

Отличить дату от внутренней метки в диагностике

$dateJson=json_encode($eventAt->jsonSerialize(),JSON_THROW_ON_ERROR);

У даты ключ $date, у marker — $timestamp; типы восстанавливаются раздельно.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTimeInterface::toDateTimeПолучить представление даты через тип UTCDateTimeInterface.

Метод с ext-mongodb 1.3.0; tentative return types с 1.15.0, обязательны с 2.0.0. · mongodb

abstract public function MongoDB\BSON\UTCDateTimeInterface::toDateTime(): DateTime

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Изменяемое PHP-представление момента. По контракту интерфейса возвращённый DateTime должен использовать UTC.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Контракт представления не подменяет проверку входной даты, выбор зоны или предметную семантику. Собственная реализация должна соблюдать объявленный тип результата.

Версии

Метод с ext-mongodb 1.3.0; tentative return types с 1.15.0, обязательны с 2.0.0.

Создать отдельное представление для зоны пользователя

function localDate(MongoDB\BSON\UTCDateTimeInterface $date): DateTime {
    return $date->toDateTime()->setTimezone(new DateTimeZone('Europe/Moscow'));
}

В полном опыте видно отличие изменения DateTime от неизменности исходного BSON-значения.

Полная программа, данные и результат

Сопоставить две формы даты

$view = mt127Date($document['at']);

Helper с интерфейсным параметром получает mutable UTC наравне с immutable и миллисекундами.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTimeInterface::toDateTimeImmutableПолучить представление даты через тип UTCDateTimeInterface.

Метод с ext-mongodb 2.0.0. · mongodb

abstract public function MongoDB\BSON\UTCDateTimeInterface::toDateTimeImmutable(): DateTimeImmutable

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Неизменяемое PHP-представление того же момента в UTC. Операции изменения возвращают другой DateTimeImmutable.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Контракт представления не подменяет проверку входной даты, выбор зоны или предметную семантику. Собственная реализация должна соблюдать объявленный тип результата.

Версии

Метод с ext-mongodb 2.0.0.

Оставить UTC и получить местную копию

$utc = $value->toDateTimeImmutable();
$local = $utc->setTimezone($zone);

Результаты UTC и +03:00 существуют одновременно без изменения первого объекта.

Полная программа, данные и результат

Показать только выбранные заказы в местной зоне

$label = $document['created_at']->toDateTimeImmutable()->setTimezone($zone)->format('Y-m-d H:i:s.vP');

Фильтрация уже выполнена базой; PHP только оформляет два полученных значения.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\UTCDateTimeInterface::__toStringПолучить представление даты через тип UTCDateTimeInterface.

Метод с ext-mongodb 1.3.0; tentative return types с 1.15.0, обязательны с 2.0.0. · mongodb

abstract public function MongoDB\BSON\UTCDateTimeInterface::__toString(): string

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Строковое представление даты. Для BSON UTCDateTime — десятичное число миллисекунд epoch, включая знак минус, а не человекочитаемая дата.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Контракт представления не подменяет проверку входной даты, выбор зоны или предметную семантику. Собственная реализация должна соблюдать объявленный тип результата.

Версии

Метод с ext-mongodb 1.3.0; tentative return types с 1.15.0, обязательны с 2.0.0.

Увидеть единицу и сохранённую точность

$milliseconds = (string) $date;

Для даты до epoch получено -1; для момента .123 —1704067200123.

Полная программа, данные и результат

Сверить восстановленное значение

$same = (string)$restored === (string)$original;

Сравниваются точные миллисекунды, а не разные строки форматирования зон.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\TimestampКорректно читать внутреннюю BSON-метку и не путать её со временем прикладного события.

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно. · mongodb

final class MongoDB\BSON\Timestamp implements TimestampInterface, Type, JsonSerializable, Stringable

Параметры и вызов

__construct(int $increment, int $timestamp). Методы без аргументов: getIncrement(): int, getTimestamp(): int, jsonSerialize(): mixed, __toString(): string. Обратите внимание: сначала порядковая часть, затем секунды.

Возвращаемое значение

Отдельный BSON-тип из двух 4-байтных компонентов: секунд epoch и increment. Применяется внутренними механизмами MongoDB, в частности репликацией и шардингом. Это не общий тип для хранения дат: для даты заказа нужен UTCDateTime.

Ошибки и границы

В текущем x64-расширении выход каждого компонента за 0..4294967295 приводит к MongoDB\Driver\Exception\InvalidArgumentException. Ошибка чтения поля другого типа — отдельная ошибка схемы приложения.

Учебный Timestamp, записанный в обычную коллекцию, не является валидной выданной сервером меткой clusterTime или resume token. Инкремент не означает дробную часть секунды. В нашем коде не изменяется управление репликацией или сессиями.

Версии

Класс с ext-mongodb 1.0.0. JsonSerializable добавлен в 1.2.0, соответствующий BSON-интерфейс — в 1.3.0, Stringable на PHP 8+ — в 1.12.0. С 2.0.0 класс больше не реализует старый Serializable. Современные способы обмена разбираются отдельно.

Разобрать диагностическую пару

$parts = mt127Marker($document['marker']);

Читаются seconds, increment, display; серверная сортировка трёх учебных значений наблюдается в таблице.

Полная программа, данные и результат

Сверить метку после обмена

$same = mt127Marker($before) === mt127Marker($restored);

Проверяется равенство значений частей. Отдельное поле event_at остаётся BSON Date.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\TimestampInterfaceОписать тип параметра диагностической функции, читающей части BSON Timestamp.

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны. · mongodb

interface MongoDB\BSON\TimestampInterface { public function getIncrement(): int; public function getTimestamp(): int; public function __toString(): string; }

Параметры и вызов

Используется для параметров, свойств и результата. Реализован Timestamp. Три метода без аргументов возвращают increment, seconds и строковое представление.

Возвращаемое значение

Контракт чтения компонентов и отображения. Интерфейс не создаёт серверную метку и не обещает автоматическое BSON-кодирование произвольного пользовательского объекта.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

На 32-bit PHP unsigned-компоненты могут выглядеть отрицательными. Наши программы требуют x64. Типизированная функция может представить значение, но не подтвердить происхождение или пригодность для session API.

Версии

Интерфейс с ext-mongodb 1.3.0. С 1.15.0 на PHP 8+ типы результата были tentative: несоответствие вызывало deprecation, временно подавляемый ReturnTypeWillChange. С 2.0.0 типы результата обязательны.

Разобрать диагностическую пару

$parts = mt127Marker($document['marker']);

Читаются seconds, increment, display; серверная сортировка трёх учебных значений наблюдается в таблице.

Полная программа, данные и результат

Сверить метку после обмена

$same = mt127Marker($before) === mt127Marker($restored);

Проверяется равенство значений частей. Отдельное поле event_at остаётся BSON Date.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\Timestamp::__constructСоздать BSON-значение из двух явно названных компонентов для известного формата данных.

С ext-mongodb 1.0.0. Текущая сигнатура принимает два int; программы явно требуют 64-битный PHP. · mongodb

final public function MongoDB\BSON\Timestamp::__construct(int $increment, int $timestamp)

Параметры и вызов

$increment — порядковая часть внутри секунды; $timestamp — секунды Unix epoch. Оба обязательны. В BSON это unsigned 32; допустимы 0..4294967295, что целиком представимо PHP int на x64. У конструктора нет автоматического «сейчас» вместо этих двух аргументов.

Возвращаемое значение

Новый Timestamp. Сам constructor не пишет в MongoDB, не выдаёт настоящую репликационную позицию и не конвертирует increment в миллисекунды.

Ошибки и границы

MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов; границы каждого компонента реально проверены четырьмя отрицательными/переполненными случаями.

Порядок аргументов отличается от привычного «seconds, fraction» и от JSON ключей t/i. Не подставляйте сюда миллисекунды UTCDateTime. Пару (0,0) не используйте как универсальное отсутствие даты.

Версии

С ext-mongodb 1.0.0. Текущая сигнатура принимает два int; программы явно требуют 64-битный PHP.

Различить порядок внутри секунды

$marker=new MongoDB\BSON\Timestamp(7,1704067200);

Реальная сортировка трёх значений в коллекции показывает сначала seconds, затем increment.

Полная программа, данные и результат

Отвергнуть отрицательные или слишком большие компоненты

new MongoDB\BSON\Timestamp(-1,1704067200);

Ожидаемый InvalidArgumentException сохранён как исход проверки, без замены на другую метку.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\Timestamp::getIncrementПрочитать порядковую часть BSON Timestamp.

С ext-mongodb 1.3.0. · mongodb

final public function MongoDB\BSON\Timestamp::getIncrement(): int

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Возвращает increment: младшие 32 бита внутреннего Timestamp, порядковую часть операций внутри секунды; unsigned 32 читается в big-endian порядке. Это не миллисекунды.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

На 32-bit системах большие значения могут возвращаться отрицательными из-за signed PHP int; sprintf("%u", $value) позволяет получить unsigned-десятичную строку. На x64 нашего стенда они положительные. Getter не подтверждает происхождение метки.

Версии

С ext-mongodb 1.3.0.

Разделить две метки одной секунды

$ordinal=$marker->getIncrement();

Значения 7 и 8 различаются при одинаковых seconds; helper показывает оба поля отдельно.

Полная программа, данные и результат

Сверить максимальное значение после базы

$maximum=$saved->getIncrement();

На x64 прочитано 4294967295 без потери; вход 4294967296 был отвергнут раньше.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\TimestampInterface::getIncrementПрочитать порядковую часть BSON Timestamp.

С ext-mongodb 1.3.0. Tentative return type с 1.15.0; обязательный int с 2.0.0. · mongodb

abstract public function MongoDB\BSON\TimestampInterface::getIncrement(): int

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Возвращает increment: младшие 32 бита внутреннего Timestamp, порядковую часть операций внутри секунды; unsigned 32 читается в big-endian порядке. Это не миллисекунды.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

На 32-bit системах большие значения могут возвращаться отрицательными из-за signed PHP int; sprintf("%u", $value) позволяет получить unsigned-десятичную строку. На x64 нашего стенда они положительные. Getter не подтверждает происхождение метки.

Версии

С ext-mongodb 1.3.0. Tentative return type с 1.15.0; обязательный int с 2.0.0.

Разделить две метки одной секунды

$ordinal=$marker->getIncrement();

Значения 7 и 8 различаются при одинаковых seconds; helper показывает оба поля отдельно.

Полная программа, данные и результат

Сверить максимальное значение после базы

$maximum=$saved->getIncrement();

На x64 прочитано 4294967295 без потери; вход 4294967296 был отвергнут раньше.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\Timestamp::getTimestampПрочитать секундную часть BSON Timestamp.

С ext-mongodb 1.3.0. · mongodb

final public function MongoDB\BSON\Timestamp::getTimestamp(): int

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Возвращает seconds: старшие 32 бита внутреннего Timestamp, число секунд Unix epoch; unsigned 32 читается в big-endian порядке. Полного порядка без increment это число не выражает.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

На 32-bit системах большие значения могут возвращаться отрицательными из-за signed PHP int; sprintf("%u", $value) позволяет получить unsigned-десятичную строку. На x64 нашего стенда они положительные. Getter не подтверждает происхождение метки.

Версии

С ext-mongodb 1.3.0.

Объяснить переход в следующую секунду

$seconds=$marker->getTimestamp();

Метка с increment1 следующей секунды стоит после increment8 предыдущей.

Полная программа, данные и результат

Проверить сохранение секунд при JSON-обмене

$seconds=$restored->getTimestamp();

Полный пример отдельно сверяет seconds и increment, сохраняя тип Timestamp.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\TimestampInterface::getTimestampПрочитать секундную часть BSON Timestamp.

С ext-mongodb 1.3.0. Tentative return type с 1.15.0; обязательный int с 2.0.0. · mongodb

abstract public function MongoDB\BSON\TimestampInterface::getTimestamp(): int

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Возвращает seconds: старшие 32 бита внутреннего Timestamp, число секунд Unix epoch; unsigned 32 читается в big-endian порядке. Полного порядка без increment это число не выражает.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

На 32-bit системах большие значения могут возвращаться отрицательными из-за signed PHP int; sprintf("%u", $value) позволяет получить unsigned-десятичную строку. На x64 нашего стенда они положительные. Getter не подтверждает происхождение метки.

Версии

С ext-mongodb 1.3.0. Tentative return type с 1.15.0; обязательный int с 2.0.0.

Объяснить переход в следующую секунду

$seconds=$marker->getTimestamp();

Метка с increment1 следующей секунды стоит после increment8 предыдущей.

Полная программа, данные и результат

Проверить сохранение секунд при JSON-обмене

$seconds=$restored->getTimestamp();

Полный пример отдельно сверяет seconds и increment, сохраняя тип Timestamp.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\Timestamp::jsonSerializeПоказать обе части Timestamp в типизированном JSON-представлении.

С ext-mongodb 1.2.0. Официальный контракт описывает legacy Extended JSON; для целого документа выбран явный Canonical Extended JSON через Document. · mongodb

final public function MongoDB\BSON\Timestamp::jsonSerialize(): mixed

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Данные для json_encode и Extended JSON; текущий результат имеет $timestamp:{t:seconds,i:increment}. В отличие от строки PHP [increment:seconds], ключи явно обозначают смысл полей.

Ошибки и границы

Официальный контракт перечисляет MongoDB\Driver\Exception\InvalidArgumentException при ошибке разбора аргументов. Вызов с объявленной сигнатурой не требует обработки случайной сетевой ошибки: сети здесь нет. Ошибки окружающего PHP-кода и JSON-кодирования относятся к своим операциям.

Даже правильный JSON не доказывает, что метку выпустил сервер. json_decode вернёт обычные данные; для получения класса Timestamp используйте согласованный BSON-декодер.

Версии

С ext-mongodb 1.2.0. Официальный контракт описывает legacy Extended JSON; для целого документа выбран явный Canonical Extended JSON через Document.

Передать marker и event_at разными типами

$view=json_encode($marker->jsonSerialize(),JSON_THROW_ON_ERROR);

Таблица рядом показывает $timestamp и $date; fromJSON сохраняет различие классов.

Полная программа, данные и результат

Сохранить диагностические части вместе

$json=json_encode($marker,JSON_THROW_ON_ERROR);

JsonSerializable вызывается автоматически; человек также видит самостоятельные seconds/increment в фактическом результате.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\Timestamp::__toStringПолучить подпись внутренней метки для диагностического экрана.

С ext-mongodb 1.0.0; Stringable для PHP 8+ с 1.12.0. · mongodb

final public function MongoDB\BSON\Timestamp::__toString(): string

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Строковое представление. Для настоящего BSON Timestamp имеет вид [increment:seconds], например [7:1704067200]. Это не ISO8601-дата и не строковый формат для произвольной отправки в session API.

Ошибки и границы

Официальная страница не перечисляет отдельные исключения. При использовании строки учитывают контекст вывода; HTML экранируется отдельно.

Для работы с частями вызывайте getIncrement/getTimestamp, не разбирайте подпись вручную. Строка удобна оператору, но не заменяет BSON-объект или контракт Extended JSON.

Версии

С ext-mongodb 1.0.0; Stringable для PHP 8+ с 1.12.0.

Подпись упорядоченных меток

$label=(string)$marker;

Таблица показывает [7:t],[8:t],[1:t+1] рядом с раздельными числовыми компонентами.

Полная программа, данные и результат

Сверка восстановленной диагностической подписи

$label=(string)$restored;

После JSON-обмена подпись совпадает; программа также проверяет компоненты, не ограничиваясь одной строкой.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

MongoDB\BSON\TimestampInterface::__toStringПолучить подпись внутренней метки для диагностического экрана.

С ext-mongodb 1.3.0; tentative string с 1.15.0, обязательный с 2.0.0. · mongodb

abstract public function MongoDB\BSON\TimestampInterface::__toString(): string

Параметры и вызов

Параметров нет; метод вызывается на уже существующем BSON-объекте. Getter не выполняет запрос к MongoDB.

Возвращаемое значение

Строковое представление. Для настоящего BSON Timestamp имеет вид [increment:seconds], например [7:1704067200]. Это не ISO8601-дата и не строковый формат для произвольной отправки в session API.

Ошибки и границы

Страница интерфейсного метода не объявляет отдельные исключения. Реализация обязана соблюдать тип результата; пользовательская реализация может иметь собственные ошибки. Сам интерфейс не выполняет сетевых действий.

Для работы с частями вызывайте getIncrement/getTimestamp, не разбирайте подпись вручную. Строка удобна оператору, но не заменяет BSON-объект или контракт Extended JSON.

Версии

С ext-mongodb 1.3.0; tentative string с 1.15.0, обязательный с 2.0.0.

Подпись упорядоченных меток

$label=(string)$marker;

Таблица показывает [7:t],[8:t],[1:t+1] рядом с раздельными числовыми компонентами.

Полная программа, данные и результат

Сверка восстановленной диагностической подписи

$label=(string)$restored;

После JSON-обмена подпись совпадает; программа также проверяет компоненты, не ограничиваясь одной строкой.

Полная программа, данные и результат

Связи: базовые BSON-типы и ранее описанные constructor/getter, типизированный Document и Extended JSON, даты и зоны PHP.

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

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

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

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

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