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

Дерево руководства
Глава 173 · После первого запроса и вставки документов
MongoDB: как выбрать узел, задать видимость чтения и подтвердить запись
От пустого документа настроек до маршрута публикации, тегов площадки, журналирования и переноса старых режимов getMode и hedge.
Какие данные покажет редакционный сервис
Как выпуск попадает в ленту
Редакция сохранила три выпуска. Для читателя нужны номер и редакция каждого опубликованного выпуска. В примере на экране будут две строки — issue-41 с редакцией 3 и issue-43 с редакцией 1. Выпуск issue-42 остаётся черновиком.
| Когда | Что решает программа | Настройка в PHP |
|---|---|---|
| Редактор сохраняет выпуски | Какого подтверждения дождаться перед сообщением «Сохранено»? В примере требуется подтверждение большинства. | WriteConcern для операции записи |
| Читатель открывает ленту | Какой узел может ответить на запрос? Первичный узел принимает записи. Вторичные узлы, если они есть, получают копии данных. | ReadPreference для выбора узла |
| Выбранный узел ищет выпуски | Какие изменения разрешено прочитать? Для этой ленты используется уровень majority, чтобы читать данные, достигшие точки подтверждения большинством. | ReadConcern для чтения |
Статус published — поле самого выпуска. Именно фильтр по этому полю убирает черновик. Если снять фильтр и оставить уровень majority, подтверждённый черновик тоже попадёт в ответ. Проекция определяет, какие поля из каждой найденной записи получит PHP.
Проследите этот путь в программе и сравните его со случаем, когда приложению разрешено читать со вторичного узла. Запись трёх выпусков и вывод двух · Как узнать, какой узел ответил.
Политика — это объект с требованиями к операции. Она не открывает страницу и сама ничего не записывает. Менеджер драйвера передаёт требования при выполнении запроса. Из полученного курсора приложение читает уже найденные документы, а из квитанции записи — сведения об изменениях.
$read = new MongoDB\Driver\ReadConcern('majority');
$description = $read->bsonSerialize();
echo $description->level; // majorityВ первой строке new создаёт объект. Текст в скобках задаёт допустимый уровень чтения. Знак = сохраняет объект в переменной $read. Во второй строке стрелка -> вызывает метод, а пустые скобки означают, что дополнительных аргументов нет. В третьей строке ->level читает поле из полученного описания. Для этих трёх строк достаточно расширения mongodb. Позже в тех же примерах используем построенные объекты при работе с настоящей базой.
Если вы впервые читаете PHP с объектами, откройте устройство объекта и метода. Порядок работы с запросом показан в главах первая страница каталога и запись и чтение через PHP-драйвер.
Куда передавать настройки PHP-драйверу
| Операция в PHP | Что туда передать | Что получите |
|---|---|---|
| new Query($filter, $options) | ReadConcern в $options["readConcern"] | Фильтр и допустимая видимость для поиска. Поля ответа выбирает projection. |
| executeQuery($namespace, $query, $options) | ReadPreference в $options["readPreference"] | Курсор. После выполнения getServer() указывает на конкретный сервер запроса. |
| executeBulkWrite($namespace, $batch, $options) | WriteConcern в $options["writeConcern"] | При успешной подтверждённой записи квитанция WriteResult содержит счётчики. |
| bsonSerialize() | Готовая политика, метод без параметров | Объект PHP с настройками. Для строки журнала вызывают json_encode() отдельно. |
В URI, у менеджера или на уровне сервера могут действовать настройки по умолчанию. В примерах режим для конкретной операции указан там, где читатель может его увидеть. Пустой объект ReadConcern оставляет уровень незаданным. Эта граница особенно важна при разборе чужих журналов.
Проверяйте три разных исхода. Конструктор может отклонить нелогичную конфигурацию ещё до обращения к базе. Допустимая конфигурация может оставить клиент без подходящего узла. После выполнения записи у сервера может возникнуть ошибка подтверждения уже применённого изменения.
Как запустить программу и открыть результат
Восемь архивов независимы. В каждом есть файл example.php с предметными действиями, policy-lab.php с подключением и отчётом и README.txt с командами создания учебной базы. Для воспроизведения использованы PHP CLI 8.5.11 x64 с ext-mongodb 2.5.5 и MongoDB 8.0.34. У одноузлового набора phpmanRs один primary без тегов площадки. Он принимает запись и позволяет увидеть выбор запасного маршрута.
$env:PHPMAN_MONGODB_URI='mongodb://127.0.0.1:27076/?replicaSet=phpmanRs&retryWrites=false'
$env:PHPMAN_MONGODB_DATABASE='php_manual_txn_lab'
php example.phpВыполните эти команды PowerShell из папки распакованного примера, когда локальная реплика будет готова принимать записи. Откройте result.html с таблицей результата. В result.json лежат те же данные, а в metrics.json — дополнительные сведения о запуске. Для каждого запуска создаётся отдельная временная коллекция. В finally программа удаляет её и затем проверяет удаление. При принудительном завершении процесса finally может не успеть выполниться.
Проверить, задан ли уровень чтения у редактора
У редактора открылась версия 7. Чтобы повторить его запрос, поддержке нужно узнать, указывал ли клиент конкретный уровень чтения.
На чём проверяем
В коллекции один материал notice. У него есть номер редакции edition и служебное поле internalNote. Запрос выбирает только номер редакции.
- Создаём ReadConcern() → уровень в клиенте не указан
- Задаём local явно → появляется поле level
- Для каждого варианта читаем notice → обе страницы показывают версию 7
Короткая запись
$visibility = new ReadConcern();
$description = $visibility->bsonSerialize();
echo json_encode($description); // {}Что получилось
| Настройка | Описание в JSON | Версия материала |
|---|---|---|
| По умолчанию | {} | 7 |
| Явно задано | {"level":"local"} | 7 |
Разбор результата
Метод bsonSerialize() возвращает объект PHP. В строку для отчёта его превращает отдельный вызов json_encode(). Пустой объект сообщает, что уровень не был задан на этом объекте. Итоговый выбор может зависеть от унаследованных настроек.
На что обратить внимание
Совпадение двух чисел относится к этой записи и этому запуску. Пустой документ в настройках клиента сам по себе не определяет эффективный уровень всего развёртывания.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-visibility-document', ['Настройка', 'Описание в JSON', 'Версия материала'], function (Manager $manager, string $namespace): array {
insertDocuments($manager, $namespace, [['_id' => 'notice', 'edition' => 7, 'internalNote' => 'draft']]);
$inherited = new ReadConcern();
$explicit = new ReadConcern(ReadConcern::LOCAL);
$rows = [];
foreach (['По умолчанию' => $inherited, 'Явно задано' => $explicit] as $label => $policy) {
$description = $policy->bsonSerialize();
[$docs] = readPage($manager, $namespace, ['_id' => 'notice'], ['_id' => 0, 'edition' => 1], $policy);
$rows[] = [$label, json_encode($description, JSON_THROW_ON_ERROR), $docs[0]['edition']];
$checks['only_public_field'] = ($checks['only_public_field'] ?? true) && array_keys($docs[0]) === ['edition'];
}
$checks['default_has_no_level'] = !property_exists($inherited->bsonSerialize(), 'level');
$checks['default_is_object'] = $inherited->bsonSerialize() instanceof stdClass;
$checks['explicit_local'] = $explicit->bsonSerialize()->level === 'local';
$checks['both_edition_seven'] = array_column($rows, 2) === [7, 7];
return [$rows, $checks, ['default_level' => $inherited->getLevel(), 'explicit_level' => $explicit->getLevel()]];
});
echo 'mongodb130-policy-visibility-document' . ": OK\n";
Ожидаемый результат
mongodb130-policy-visibility-document: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Уберите projection из полного запроса. В результате появится internalNote и проверка only_public_field покажет, почему в интерфейс лучше отдавать только нужные поля.
Вывести только опубликованные выпуски с подтверждёнными данными
Лента выпусков должна показывать опубликованные редакции, достигшие точки подтверждения большинства. Черновики в ленту не попадают.
На чём проверяем
Создадим три выпуска, из которых опубликованы 41 и 43. WriteConcern задаёт условие получения квитанции на вставку, ReadConcern задаёт допустимое состояние данных при отдельном чтении.
- Вставляем три выпуска с w=majority → квитанция за три документа
- ReadConcern(majority) → допустимы подтверждённые данные
- Фильтр published и проекция → две строки ленты
Короткая запись
$visibility = new ReadConcern(ReadConcern::MAJORITY);
$query = new MongoDB\Driver\Query(['state' => 'published'], [
'readConcern' => $visibility,
'projection' => ['_id' => 1, 'edition' => 1],
]);Что получилось
| Выпуск | Версия | Уровень чтения |
|---|---|---|
| issue-41 | 3 | majority |
| issue-43 | 1 | majority |
Разбор результата
Два разных условия решают две задачи. Фильтр state исключил черновик. Уровень majority ограничил видимость чтения точкой подтверждения на выбранном узле. Он не выбирает строки по значению state и не выбирает сам узел.
На что обратить внимание
На одноузловой реплике большинство состоит из одного узла с данными. Пример не измеряет отставание между машинами. В большом наборе точка majority на вторичном узле может отставать.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-committed-feed', ['Выпуск', 'Версия', 'Уровень чтения'], function (Manager $manager, string $namespace): array {
$write = new WriteConcern(WriteConcern::MAJORITY, 2000);
$receipt = insertDocuments($manager, $namespace, [
['_id' => 'issue-41', 'state' => 'published', 'edition' => 3],
['_id' => 'issue-42', 'state' => 'draft', 'edition' => 8],
['_id' => 'issue-43', 'state' => 'published', 'edition' => 1],
], $write);
$read = new ReadConcern(ReadConcern::MAJORITY);
[$docs, $server] = readPage($manager, $namespace, ['state' => 'published'], ['_id' => 1, 'edition' => 1], $read);
$rows = [];
foreach ($docs as $doc) {
$rows[] = [$doc['_id'], $doc['edition'], $read->bsonSerialize()->level];
}
$checks['three_written'] = $receipt->getInsertedCount() === 3;
$checks['write_w_majority'] = $write->bsonSerialize()->w === 'majority';
$checks['published_only'] = array_column($docs, '_id') === ['issue-41', 'issue-43'];
$checks['projected_fields'] = !array_key_exists('state', $docs[0]);
$checks['editions'] = array_column($docs, 'edition') === [3, 1];
return [$rows, $checks, ['acknowledged' => $receipt->isAcknowledged(), 'read_options' => $read->bsonSerialize(), 'primary' => $server->getType() === Server::TYPE_RS_PRIMARY]];
});
echo 'mongodb130-policy-committed-feed' . ": OK\n";
Ожидаемый результат
mongodb130-policy-committed-feed: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Добавьте выпуск issue-44 в состоянии draft. Квитанция вставки теперь покажет четыре, но в выдаче по-прежнему будут две строки. Обновите проверку количества вставок.
Как связаны подтверждённая запись, видимый результат чтения и свежесть конкретной копии? Раздельно предъявить WriteResult и прочитанные опубликованные выпуски при majority; явно указать границу одноузлового опыта. Вопрос разработчика на Stack Overflow.
Прочитать номер активной редакции перед отправкой рассылки
Перед отправкой рассылки сервису нужен один авторитетный номер текущей редакции. Ранее завершившаяся запись указателя с w=majority должна учитываться.
На чём проверяем
Документ active-release уникален по _id. Запись версии 18 завершится до чтения. Режим linearizable на основном узле даёт этому одиночному чтению нужную гарантию упорядочения.
- Подтверждаем запись редакции 18
- По уникальному _id идём на primary с linearizable
- Возвращается только число 18; время работы запроса ограничено maxTimeMS
Короткая запись
$query = new MongoDB\Driver\Query(['_id' => 'active-release'], [
'readConcern' => new ReadConcern('linearizable'),
'projection' => ['_id' => 0, 'revision' => 1],
'maxTimeMS' => 2000,
]);
$cursor = $manager->executeQuery($namespace, $query, ['readPreference' => new ReadPreference('primary')]);Что получилось
| Ключ | Редакция | Уровень |
|---|---|---|
| active-release | 18 | linearizable |
Разбор результата
Разделяйте три части вызова. _id выбирает документ. ReadPreference указывает на primary. Свойство readConcern запроса задаёт линейное чтение. maxTimeMS ограничивает ожидание выполнения на сервере в миллисекундах.
На что обратить внимание
Гарантия относится к чтению одного однозначно найденного документа. Она не делает две отдельные операции атомарными. Если после чтения другой редактор может сменить номер, для изменения указателя используйте также условие на прежнюю версию.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-single-record', ['Ключ', 'Редакция', 'Уровень'], function (Manager $manager, string $namespace): array {
$receipt = insertDocuments($manager, $namespace, [
['_id' => 'active-release', 'revision' => 18, 'recipientList' => 'private'],
], new WriteConcern('majority', 2000));
$visibility = new ReadConcern(ReadConcern::LINEARIZABLE);
$route = new ReadPreference(ReadPreference::PRIMARY);
[$docs, $server] = readPage($manager, $namespace, ['_id' => 'active-release'], ['_id' => 0, 'revision' => 1], $visibility, $route);
$checks['one_insert'] = $receipt->getInsertedCount() === 1;
$checks['one_record'] = count($docs) === 1;
$checks['selected_primary'] = $server->getType() === Server::TYPE_RS_PRIMARY;
$checks['level'] = $visibility->bsonSerialize()->level === 'linearizable';
$checks['only_revision'] = $docs === [['revision' => 18]];
return [[['active-release', $docs[0]['revision'], $visibility->getLevel()]], $checks, [
'maxTimeMS' => 2000, 'requested_route' => $route->bsonSerialize(), 'acknowledged_writes' => $receipt->getInsertedCount(),
]];
});
echo 'mongodb130-policy-single-record' . ": OK\n";
Ожидаемый результат
mongodb130-policy-single-record: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Попробуйте искать _id, которого нет. Корректная предметная ветвь здесь — пропустить рассылку. Пустой курсор надо обработать до обращения к первой строке.
Узнать, откуда пришла страница при secondaryPreferred
На странице новостей разрешено использовать вторичную копию, если она доступна. Именно на учебном сервере без вторичных узлов нужно понять, почему страница всё-таки открывается.
На чём проверяем
Документ press содержит заголовок и внутреннюю заметку. ReadPreference с окончанием Preferred разрешает запасной вариант.
- executeQuery получает режим secondaryPreferred
- Среди узлов нет secondary → выбирается primary
- getServer() у этого курсора показывает primary; читатель видит заголовок
Короткая запись
$route = new ReadPreference(ReadPreference::SECONDARY_PREFERRED);
$cursor = $manager->executeQuery($namespace, $query, ['readPreference' => $route]);
$actualServer = $cursor->getServer();Что получилось
| Запрошено | Ответил | На странице |
|---|---|---|
| secondaryPreferred | primary | Итоги недели |
Разбор результата
getModeString() и bsonSerialize() описывают то, что просил клиент. Курсор принадлежит уже выполненному запросу. Его getServer() даёт место исполнения именно этой операции. Этими двумя значениями удобно объяснить поведение страницы поддержке.
На что обратить внимание
Режим secondary исключает primary. В таком же наборе запрос с ним завершится ошибкой выбора сервера. Даже если запрос обслуживает secondary, это никак не заменяет настройки ReadConcern.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-preferred-route', ['Запрошено', 'Ответил', 'На странице'], function (Manager $manager, string $namespace): array {
insertDocuments($manager, $namespace, [['_id' => 'press', 'headline' => 'Итоги недели', 'privateMemo' => 99]]);
$route = new ReadPreference(ReadPreference::SECONDARY_PREFERRED);
[$docs, $server] = readPage($manager, $namespace, ['_id' => 'press'], ['_id' => 0, 'headline' => 1], null, $route);
$isPrimary = $server->getType() === Server::TYPE_RS_PRIMARY;
$checks['preferred_mode'] = $route->getModeString() === 'secondaryPreferred';
$checks['serialized_mode'] = $route->bsonSerialize()->mode === $route->getModeString();
$checks['fallback_primary'] = $isPrimary;
$checks['exact_card'] = $docs === [['headline' => 'Итоги недели']];
$checks['no_route_tags'] = $route->getTagSets() === [];
return [[[$route->getModeString(), $isPrimary ? 'primary' : 'other', $docs[0]['headline']]], $checks,
['requested' => $route->bsonSerialize(), 'served_by' => $server->getHost(), 'type' => $server->getType()]];
});
echo 'mongodb130-policy-preferred-route' . ": OK\n";
Ожидаемый результат
mongodb130-policy-preferred-route: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Смените маршрут на primaryPreferred. В первой ячейке появится другое запрошенное значение, вторая останется primary. Сравните эти колонки.
Как понять, с какого узла пришла карточка при отсутствии подходящей вторичной реплики? Сопоставить запрошенный режим с реальной ролью сервера, вернувшего курсор. Вопрос разработчика на Stack Overflow.
Разрешить резервный узел, когда нужной площадки нет
Для региональной ленты предпочтителен узел на площадке east. Сайт может показать ленту с другой площадки, если это допустимо по правилам сервиса.
На чём проверяем
У единственного узла стенда нет тега dc=east. Вторая политика содержит упорядоченный список из двух наборов тегов. Пустой документ в конце совпадает с любым подходящим по режиму узлом.
- nearest + только dc=east → кандидатов нет
- nearest + [dc=east, {}] → второй набор допускает primary
- Запрос возвращает items=12; сериализация сохраняет оба условия по порядку
Короткая запись
$route = new ReadPreference('nearest', [
['dc' => 'east'],
[], // В BSON это пустой документ {}.
]);
$description = $route->bsonSerialize();Что получилось
| Правило | Исход запроса | Записей в выпуске |
|---|---|---|
| Только east | нет подходящего узла | null |
| east, затем любой | ответ | 12 |
Разбор результата
Каждый набор условий проверяется по очереди. После первого подходящего набора драйвер выбирает среди подходящих узлов в окне сетевой задержки. Имя nearest не обещает фиксированный адрес. Условия тегов относятся к узлам, а не к полям документов.
На что обратить внимание
Отказ первого запроса ограничен serverSelectionTimeoutMS на клиенте. Эта задержка не означает, что запрос медленно выполнялся в базе. При политике secondary пустой набор тегов не поможет, если нет ни одного secondary.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-region-fallback', ['Правило', 'Исход запроса', 'Записей в выпуске'], function (Manager $manager, string $namespace): array {
insertDocuments($manager, $namespace, [['_id' => 'east-news', 'items' => 12]]);
$strict = new ReadPreference('nearest', [['dc' => 'east']]);
$withFallback = new ReadPreference('nearest', [['dc' => 'east'], []]);
$selectionFailed = false;
try {
readPage($manager, $namespace, ['_id' => 'east-news'], ['items' => 1], null, $strict);
} catch (ConnectionTimeoutException $error) {
$selectionFailed = true;
}
[$docs, $server] = readPage($manager, $namespace, ['_id' => 'east-news'], ['_id' => 0, 'items' => 1], null, $withFallback);
$tags = $withFallback->bsonSerialize()->tags;
$checks['strict_tag_unavailable'] = $selectionFailed;
$checks['two_tag_documents'] = count($tags) === 2 && $tags[1] instanceof stdClass;
$checks['first_tag_east'] = $tags[0]->dc === 'east';
$checks['last_tag_any'] = get_object_vars($tags[1]) === [];
$checks['secondary_not_required'] = $server->getType() === Server::TYPE_RS_PRIMARY;
$checks['read_count'] = $docs === [['items' => 12]];
return [[['Только east', $selectionFailed ? 'нет подходящего узла' : 'ответ', null],
['east, затем любой', 'ответ', $docs[0]['items']]], $checks, ['requested' => $withFallback->bsonSerialize()]];
});
echo 'mongodb130-policy-region-fallback' . ": OK\n";
Ожидаемый результат
mongodb130-policy-region-fallback: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Уберите последний пустой набор. Должна сработать ветвь отсутствия подходящего узла. Добавляйте запасной маршрут только если выход за площадку разрешён.
Непонятно, когда пустой набор тегов поможет выбрать сервер. Сравнить строгий nearest с dc=east и тот же nearest со вторым пустым документом на стенде без тегов. Вопрос разработчика на Stack Overflow.
Проверить условия подтверждения перед выпуском материала
Выпуск попадает к читателям после подтверждения записи. Для диагностики издателю нужны и условия, которые запросил сервис, и ответ на конкретную вставку.
На чём проверяем
У редактора два профиля. Черновик требует w=1. Для выпуска указаны majority, журналирование и 2500 миллисекунд ожидания write concern. Оба материала вставляются по одному разу.
- WriteConcern(1) → в описании только w
- WriteConcern(majority, 2500, true) → поля w, wtimeout и j
- Две вставки → две отдельные квитанции, по одной строке
Короткая запись
$publish = new WriteConcern(WriteConcern::MAJORITY, 2500, true);
$requested = $publish->bsonSerialize();
$receipt = $manager->executeBulkWrite($namespace, $batch, ['writeConcern' => $publish]);Что получилось
| Материал | w | j | wtimeout, мс | Вставлено |
|---|---|---|---|---|
| Черновик | 1 | null | null | 1 |
| Выпуск | majority | true | 2500 | 1 |
Разбор результата
Метод bsonSerialize() формирует документ настроек. Поле j описывает запрошенное журналирование. Квитанция WriteResult отражает выполненную операцию. null в таблице для первого профиля означает, что соответствующего поля в документе нет. Это отличается от явного j=false.
На что обратить внимание
Лимит wtimeout относится к ожиданию нужного подтверждения записи. Истечение этого времени само по себе не отменяет уже внесённое изменение. В наборе с одним голосующим узлом majority достижим, но дополнительной физической копии здесь нет.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-write-profile', ['Материал', 'w', 'j', 'wtimeout, мс', 'Вставлено'], function (Manager $manager, string $namespace): array {
$policies = [
'Черновик' => new WriteConcern(1),
'Выпуск' => new WriteConcern(WriteConcern::MAJORITY, 2500, true),
];
$rows = [];
$profiles = [];
foreach ($policies as $kind => $policy) {
$document = $policy->bsonSerialize();
$receipt = insertDocuments($manager, $namespace, [['_id' => $kind, 'stage' => $kind]], $policy);
$profiles[$kind] = $document;
$rows[] = [$kind, $document->w, $document->j ?? null, $document->wtimeout ?? null, $receipt->getInsertedCount()];
$checks['both_acknowledged'] = ($checks['both_acknowledged'] ?? true) && $receipt->isAcknowledged();
}
[$persisted] = readPage($manager, $namespace, [], ['_id' => 0, 'stage' => 1], new ReadConcern('majority'));
$checks['two_stored'] = count($persisted) === 2;
$checks['draft_fields'] = array_keys(get_object_vars($profiles['Черновик'])) === ['w'];
$checks['release_journal'] = $profiles['Выпуск']->j === true;
$checks['release_wait'] = $profiles['Выпуск']->wtimeout === 2500;
$checks['release_majority'] = $profiles['Выпуск']->w === 'majority';
return [$rows, $checks, ['requested' => $profiles, 'stored_stages' => array_column($persisted, 'stage')]];
});
echo 'mongodb130-policy-write-profile' . ": OK\n";
Ожидаемый результат
mongodb130-policy-write-profile: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Поставьте для выпуска wtimeout=1000 и сравните документ настроек и квитанцию. Поменяется записанный лимит. Не следует ожидать, что успешная вставка станет длиться ровно секунду.
Перенести числовой профиль старого сервиса на современные режимы
В сохранённой конфигурации сайта лежит число 6. Новый PHP-драйвер задаёт режим строкой. Нужно понять старое значение и обнаружить неизвестные настройки до отправки запроса.
На чём проверяем
Два документа в базе содержат прежние режимы 6 и 77. На старом API getMode() возвращал целое число. На ext-mongodb 2.x эта функция удалена.
- Считываем сохранённое целое 6 → сверяем с закрытой таблицей прежних режимов
- Создаём ReadPreference(secondaryPreferred) → страница отдаёт версию 4
- Число 77 отсутствует в таблице → требуется ручное решение
Короткая запись
$oldModes = [1 => 'primary', 5 => 'primaryPreferred', 2 => 'secondary', 6 => 'secondaryPreferred', 10 => 'nearest'];
$old = 6;
$route = new ReadPreference($oldModes[$old]);
echo $route->getModeString(); // secondaryPreferredЧто получилось
| Старое число | Решение | Версия прочитанной страницы |
|---|---|---|
| 6 | secondaryPreferred | 4 |
| 77 | нужен разбор | null |
Разбор результата
Миграция переводит известное число в имя режима до создания ReadPreference. getModeString() возвращает строку и подходит для журналов. К неизвестному числу программа не подставляет произвольный запасной маршрут.
На что обратить внимание
Старый getMode() здесь только описан. В исполняемой программе используется method_exists для проверки его отсутствия. Исторические числа применяйте лишь для данных, у которых точно известен формат прежнего драйвера.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-legacy-mode', ['Старое число', 'Решение', 'Версия прочитанной страницы'], function (Manager $manager, string $namespace): array {
insertDocuments($manager, $namespace, [
['_id' => 'route-cache', 'oldMode' => 6],
['_id' => 'route-unknown', 'oldMode' => 77],
['_id' => 'daily-page', 'edition' => 4],
]);
[$settings] = readPage($manager, $namespace, ['oldMode' => ['$exists' => true]], ['_id' => 1, 'oldMode' => 1]);
$oldModes = [1 => 'primary', 5 => 'primaryPreferred', 2 => 'secondary', 6 => 'secondaryPreferred', 10 => 'nearest'];
$rows = [];
foreach ($settings as $setting) {
$old = $setting['oldMode'];
if (!is_int($old) || !isset($oldModes[$old])) {
$rows[] = [$old, 'нужен разбор', null];
continue;
}
$route = new ReadPreference($oldModes[$old]);
[$page] = readPage($manager, $namespace, ['_id' => 'daily-page'], ['_id' => 0, 'edition' => 1], null, $route);
$rows[] = [$old, $route->getModeString(), $page[0]['edition']];
}
$checks['old_getter_removed'] = !method_exists(ReadPreference::class, 'getMode');
$checks['modern_getter_exists'] = method_exists(ReadPreference::class, 'getModeString');
$checks['two_profiles'] = count($settings) === 2;
$checks['known_mode_read'] = $rows[0] === [6, 'secondaryPreferred', 4];
$checks['unknown_quarantined'] = $rows[1] === [77, 'нужен разбор', null];
return [$rows, $checks, ['known_old_values' => $oldModes, 'old_getter_present' => method_exists(ReadPreference::class, 'getMode')]];
});
echo 'mongodb130-policy-legacy-mode' . ": OK\n";
Ожидаемый результат
mongodb130-policy-legacy-mode: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Передайте строку "6" вместо целого 6. В этой схеме она должна попасть на разбор. Если исходная система официально хранит строковые числа, введите отдельную проверку формата и только затем выполняйте преобразование.
Прочитать старую настройку hedge и проверить маршрут после её удаления
Сервис готовит обновление конфигурации с давним параметром hedge. Оператору необходимо различить «явно выключено» и «параметр отсутствует», затем проверить чтение после переноса.
На чём проверяем
В сохранённом профиле указаны nearest и enabled=false. Старый объект нужен только для обследования конфигурации. У нового объекта режим тот же, а опция отсутствует.
- Загружаем профиль → getHedge() возвращает объект с enabled=false
- Создаём политику без hedge → getter возвращает null
- Отправляем запрос с новой политикой → получаем «Вечерний выпуск»
Короткая запись
$clean = new ReadPreference('nearest');
$description = $clean->bsonSerialize();
echo property_exists($description, 'hedge') ? 'поле задано' : 'поле отсутствует';Что получилось
| Профиль | Значение enabled | Режим |
|---|---|---|
| До переноса | false | nearest |
| После переноса | null | nearest |
Разбор результата
Метод getHedge() самой версии 2.5.5 доступен и помечен устаревшим. Узкий обработчик E_DEPRECATED сохраняет сообщения именно про hedge в деталях опыта и восстанавливает прежний обработчик в finally. Объект с enabled=false и отсутствие объекта — разные сведения о конфигурации.
На что обратить внимание
Hedged reads были возможностью mongos в шардированном кластере для чтения с непервичным режимом. Сервер MongoDB 8.0 пометил механизм устаревшим. У одноузлового учебного replica set нет mongos: здесь выполнен один запрос с очищенной политикой, соревнования двух чтений не происходило.
Открыть полную программу и скачать архив
<?php
declare(strict_types=1);
require __DIR__.'/policy-lab.php';
use MongoDB\Driver\{Manager, ReadConcern, ReadPreference, WriteConcern, Server};
use MongoDB\Driver\Exception\{ConnectionTimeoutException, InvalidArgumentException};
runLesson('mongodb130-policy-hedge-audit', ['Профиль', 'Значение enabled', 'Режим'], function (Manager $manager, string $namespace): array {
insertDocuments($manager, $namespace, [
['_id' => 'reader-profile', 'mode' => 'nearest', 'hedge' => ['enabled' => false]],
['_id' => 'edition-card', 'title' => 'Вечерний выпуск'],
]);
[$settings] = readPage($manager, $namespace, ['_id' => 'reader-profile'], ['_id' => 0, 'mode' => 1, 'hedge' => 1]);
$profile = $settings[0];
$warnings = [];
set_error_handler(static function (int $severity, string $message) use (&$warnings): bool {
if ($severity !== E_DEPRECATED || stripos($message, 'hedge') === false) {
return false;
}
$warnings[] = $message;
return true;
}, E_DEPRECATED);
try {
$historical = new ReadPreference($profile['mode'], null, ['hedge' => $profile['hedge']]);
$explicit = $historical->getHedge();
$clean = new ReadPreference($profile['mode']);
$omitted = $clean->getHedge();
} finally {
restore_error_handler();
}
[$page, $server] = readPage($manager, $namespace, ['_id' => 'edition-card'], ['_id' => 0, 'title' => 1], null, $clean);
$checks['old_explicit_false'] = $explicit instanceof stdClass && $explicit->enabled === false;
$checks['clean_omitted'] = $omitted === null;
$checks['warnings_recorded'] = count($warnings) > 0;
$checks['same_mode'] = $historical->getModeString() === $clean->getModeString();
$checks['field_removed'] = !property_exists($clean->bsonSerialize(), 'hedge');
$checks['served_card'] = $page === [['title' => 'Вечерний выпуск']] && $server->getType() === Server::TYPE_RS_PRIMARY;
return [[['До переноса', $explicit->enabled, $historical->getModeString()],
['После переноса', $omitted, $clean->getModeString()]], $checks,
['php_deprecations' => $warnings, 'queried_title' => $page[0]['title'], 'used_route' => $clean->bsonSerialize()]];
});
echo 'mongodb130-policy-hedge-audit' . ": OK\n";
Ожидаемый результат
mongodb130-policy-hedge-audit: OK
Запускайте example.php из распакованного архива с policy-lab.php. Фактическую таблицу программа сохраняет в result.html и result.json.
Посмотреть результат запуска · Открыть строки результата в JSON
Попробуйте сами
Сохраните второй профиль без поля hedge и покажите его отдельной строкой «отсутствует». Создавайте исторический объект с опцией только если поле действительно присутствует.
Классы и методы для проверки профиля
| Класс или метод | Когда открыть карточку |
|---|---|
| MongoDB\Driver\ReadConcern | Определить, какое состояние документов допускает чтение. |
| MongoDB\Driver\ReadPreference | Выбрать допустимый маршрут для конкретного чтения. |
| MongoDB\Driver\WriteConcern | Описать требуемое подтверждение записи. |
| MongoDB\Driver\ReadConcern::bsonSerialize | Посмотреть документ настройки видимости чтения. |
| MongoDB\Driver\ReadPreference::bsonSerialize | Вывести маршрут чтения вместе с порядком наборов тегов. |
| MongoDB\Driver\WriteConcern::bsonSerialize | Получить документ запроса на подтверждение записи. |
| MongoDB\Driver\ReadPreference::getMode | Понять числовой режим из старого кода и перенести его на PHP-драйвер 2.x. |
| MongoDB\Driver\ReadPreference::getHedge | Проверить параметр hedge в наследованной конфигурации. |
Как связать два последовательных запроса
Одиночная политика описывает одну сторону операции. Чтобы объяснить порядок действий клиента, например когда второе чтение должно учитывать предшествующую запись, переходите к главе о сессиях и времени операций. Для показаний конкретной квитанции пригодится разбор WriteResult и ошибок подтверждения.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
MongoDB\Driver\ReadConcernОпределить, какое состояние документов допускает чтение.
ReadConcern с ext-mongodb 1.1.0, BSON-сериализация и LINEARIZABLE с 1.2, AVAILABLE с 1.4, SNAPSHOT с 1.11, публичное readonly-свойство с 2.3. · mongodb
final class MongoDB\Driver\ReadConcern implements MongoDB\BSON\SerializableВызов и параметры
new ReadConcern(?string $level = null). При пропуске аргумента клиент не фиксирует локальный уровень. Явное значение передают в опции readConcern объекта Query. getLevel() возвращает имя или null, isDefault() показывает состояние по умолчанию, readonly-свойство level доступно с 2.3.
Возвращаемое значение
Конструктор создаёт объект политики. Документы появятся в курсоре после отдельного вызова executeQuery(). local допускает локально видимые данные, включая изменения, которые ещё могут откатиться. majority ограничивает чтение подтверждённым состоянием, доступным этому узлу.
Ошибки и границы применения
available может возвращать при миграции чанков в шардированном кластере документы, уже не принадлежащие шарду, и недоступен в транзакциях и причинно-согласованных сессиях. linearizable читают на primary и применяют к однозначному поиску одного документа, с maxTimeMS. snapshot задаёт снимок в один момент времени. Он доступен в транзакциях, а с MongoDB 5.0 также для поддерживаемых операций вне транзакции. Выбор уровня требует поддержки операции на сервере.
Версии
ReadConcern с ext-mongodb 1.1.0, BSON-сериализация и LINEARIZABLE с 1.2, AVAILABLE с 1.4, SNAPSHOT с 1.11, публичное readonly-свойство с 2.3.
Лента опубликованного
$policy = new ReadConcern('majority');
$query = new MongoDB\Driver\Query(['state' => 'published'], ['readConcern' => $policy]);Фильтр задаёт статус документа. Уровень чтения задаёт допустимую видимость. В таблице два выпуска.
Открыть исходные данные, программу и её результат
Проверка перед рассылкой
$policy = new ReadConcern(ReadConcern::LINEARIZABLE);Поиск на primary по уникальному ключу active-release возвращает подтверждённую ранее версию 18.
Открыть исходные данные, программу и её результат
Дальше можно открыть Создание ReadConcern · getLevel() · isDefault().
MongoDB\Driver\ReadPreferenceВыбрать допустимый маршрут для конкретного чтения.
Класс с 1.0.0. Опции maxStalenessSeconds и BSON-сериализация с 1.2, строковый mode с 1.3, строковые константы режимов с 1.7, hedge с 1.8. Старый числовой API устарел в 1.20 и удалён в 2.0. Свойства readonly с 2.3. · mongodb
final class MongoDB\Driver\ReadPreference implements MongoDB\BSON\SerializableВызов и параметры
Конструктор принимает обязательный режим string $mode, затем ?array $tagSets и ?array $options. primary разрешает только основной узел, primaryPreferred при необходимости разрешает вторичные. secondary требует вторичный, а secondaryPreferred допускает основной при отсутствии подходящих вторичных. nearest выбирает из подходящих узлов в окне сетевой задержки, включая primary. Сначала применяются правила режима, доступности, допустимого отставания и тегов, затем учитывается окно задержки.
Возвращаемое значение
Получается объект для опции readPreference в executeQuery(). Режим читают getModeString(), наборы тегов — getTagSets(), предел отставания — getMaxStalenessSeconds(). Свойства только для чтения mode, tags, maxStalenessSeconds и устаревшее hedge описывают конфигурацию. Роль реально ответившего узла узнают через getServer() у курсора.
Ошибки и границы применения
У primary нельзя задавать непустые теги и положительный maxStalenessSeconds. Конструктор отклоняет некорректные комбинации через InvalidArgumentException. -1 означает отсутствие ограничения, установленное значение для secondary не меньше 90 секунд и должно удовлетворять требованиям драйвера к интервалу мониторинга. Это оценка отставания реплики, а не задержка выполнения текущего запроса. Если подходящих узлов нет, операция может исчерпать serverSelectionTimeoutMS.
Версии
Класс с 1.0.0. Опции maxStalenessSeconds и BSON-сериализация с 1.2, строковый mode с 1.3, строковые константы режимов с 1.7, hedge с 1.8. Старый числовой API устарел в 1.20 и удалён в 2.0. Свойства readonly с 2.3.
Показать заголовок с доступного узла
$route = new ReadPreference('secondaryPreferred');При отсутствии secondary курсор обслужен primary. Заголовок страницы остаётся доступен.
Открыть исходные данные, программу и её результат
Потребовать площадку или разрешить запасную
$route = new ReadPreference('nearest', [['dc' => 'east'], []]);Порядок наборов существенен. Сначала выбирается подходящая восточная площадка, при её отсутствии разрешается любой подходящий узел.
Открыть исходные данные, программу и её результат
Дальше можно открыть Создание ReadPreference · getTagSets() · getMaxStalenessSeconds().
MongoDB\Driver\WriteConcernОписать требуемое подтверждение записи.
Класс с 1.0.0, MongoDB\BSON\Serializable с 1.2, публичные readonly-свойства с 2.3. · mongodb
final class MongoDB\Driver\WriteConcern implements MongoDB\BSON\SerializableВызов и параметры
new WriteConcern(string|int $w, ?int $wtimeout = null, ?bool $journal = null). w=0 не запрашивает подтверждения от сервера, 1 ожидает основной узел, положительное N задаёт число подтверждающих узлов с данными. Строки задают majority или именованный режим, определённый конфигурацией replica set. wtimeout в миллисекундах ограничивает ожидание подтверждения, 0 означает отсутствие такого предела. journal=true запрашивает фиксацию в журнале.
Возвращаемое значение
Возникает объект настроек. Его передают вместе с BulkWrite. Ответ на запись находится в отдельном объекте WriteResult. getW(), getJournal(), getWtimeout() и isDefault() помогают исследовать конфигурацию. Поля w, j и wtimeout доступны только для чтения.
Ошибки и границы применения
Значение majority вычисляется по конфигурации replica set, а подтверждают запись узлы с данными. Арбитр не хранит документ. Просроченное ожидание подтверждения не откатывает применённую запись. У w=0 нет серверной квитанции для получения обычных счётчиков. В транзакции условие подтверждения задают на уровне транзакции. Некорректные аргументы и несовместимые параметры отклоняются.
Версии
Класс с 1.0.0, MongoDB\BSON\Serializable с 1.2, публичные readonly-свойства с 2.3.
Сохранение черновика и окончательного выпуска
$draft = new WriteConcern(1);
$publication = new WriteConcern('majority', 2500, true);Оба профиля сохраняют по одному документу. Подтверждение выпуска дополнительно требует журналирования.
Открыть исходные данные, программу и её результат
Дождаться подтверждения перед чтением
$receipt = $manager->executeBulkWrite($namespace, $batch, ['writeConcern' => new WriteConcern('majority', 2000)]);Сначала вставляются три записи. Следующее чтение выбирает из подтверждённого состояния только опубликованные.
Открыть исходные данные, программу и её результат
Дальше можно открыть Создание WriteConcern · getJournal() · getW() · getWtimeout() · isDefault().
MongoDB\Driver\ReadConcern::bsonSerializeПосмотреть документ настройки видимости чтения.
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass. · mongodb
final public function MongoDB\Driver\ReadConcern::bsonSerialize(): stdClassВызов и параметры
Вызов на готовом объекте без аргументов. Операция локальная: соединение с MongoDB для неё не требуется.
Возвращаемое значение
Возвращает объект для BSON-сериализации. Без явного уровня у него нет поля level. При local или majority это поле содержит соответствующую строку. json_encode() отдельно превращает результат в текст для журнала.
Ошибки и границы применения
Передавать параметры этому методу не следует. Страница PHP.net перечисляет InvalidArgumentException при разборе ошибочного вызова. Содержимое объекта говорит, что запросил данный клиент. Финальное состояние данных нужно получать отдельным чтением.
Версии
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass.
Различить отсутствие настройки и local
$description = (new ReadConcern())->bsonSerialize();
echo json_encode($description);Получается {}. Пустая политика позволяет унаследовать действующие настройки.
Открыть исходные данные, программу и её результат
Записать политику подготовки ленты
$read = new ReadConcern('majority');
echo $read->bsonSerialize()->level;В журнале появится majority. Две строки выпусков получаются отдельным запросом.
Открыть исходные данные, программу и её результат
Дальше можно открыть Получить только название уровня.
MongoDB\Driver\ReadPreference::bsonSerializeВывести маршрут чтения вместе с порядком наборов тегов.
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass. · mongodb
final public function MongoDB\Driver\ReadPreference::bsonSerialize(): stdClassВызов и параметры
Вызов на готовом объекте без аргументов. Операция локальная: соединение с MongoDB для неё не требуется.
Возвращаемое значение
Возвращает объект с именем режима и заданными параметрами. При наличии tagSets поле tags содержит массив документов. Пустой документ в списке сохраняет смысл «любой подходящий узел». maxStalenessSeconds выражается в секундах. При сериализации старой конфигурации может встретиться поле hedge.
Ошибки и границы применения
Метод имеет ноль параметров, ошибки передачи аргументов документированы как InvalidArgumentException. Сериализация не выбирает хост и не измеряет задержку. Не превращайте каждое вложенное пустое значение в обычный JSON-массив: {} и [] имеют разный смысл.
Версии
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass.
Сопоставить пожелание с результатом
$mode = $route->bsonSerialize()->mode;
$chosen = $cursor->getServer();Запрошено secondaryPreferred, а данные пришли с primary. Оба наблюдения одновременно верны.
Открыть исходные данные, программу и её результат
Проверить, сохранился ли запасной набор
$tags = $withFallback->bsonSerialize()->tags;
echo json_encode($tags);На экране [{"dc":"east"},{}]. Второй документ позволяет обслужить запрос при отсутствии тега east.
Открыть исходные данные, программу и её результат
Дальше можно открыть Наборы тегов · Только название режима.
MongoDB\Driver\WriteConcern::bsonSerializeПолучить документ запроса на подтверждение записи.
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass. · mongodb
final public function MongoDB\Driver\WriteConcern::bsonSerialize(): stdClassВызов и параметры
Вызов на готовом объекте без аргументов. Операция локальная: соединение с MongoDB для неё не требуется.
Возвращаемое значение
Возвращает документ PHP со значениями w и явно заданными параметрами. Например, при majority, 2500 и true видны строка w, число wtimeout и логическое j. Получить текст отчёта можно через json_encode().
Ошибки и границы применения
Метод вызывается без аргументов. PHP.net указывает InvalidArgumentException при неверном разборе аргументов. Если в представлении простого профиля отсутствуют j и wtimeout, их нельзя выдавать за явно установленное false или за фактически прошедшее время.
Версии
Метод доступен с ext-mongodb 1.2.0. В 2.5.5 тип результата — stdClass.
Объяснить, какое ожидание задано
$options = (new WriteConcern('majority', 2500, true))->bsonSerialize();
echo $options->wtimeout;Получаем 2500 миллисекунд настройки подтверждения выпуска. Время операции здесь не измеряется.
Открыть исходные данные, программу и её результат
Сопоставить настройку и квитанцию партии
$required = $write->bsonSerialize()->w;
$inserted = $receipt->getInsertedCount();Профиль даёт строку majority, квитанция даёт число 3. Количество возвращённых выпусков в ленте равно 2 по независимой причине — фильтру состояния.
Открыть исходные данные, программу и её результат
Дальше можно открыть Посмотреть w · Диагностика ответа на запись.
MongoDB\Driver\ReadPreference::getModeПонять числовой режим из старого кода и перенести его на PHP-драйвер 2.x.
Введён в 1.0.0, устарел в 1.20.0, удалён в 2.0.0. Исторический getter в программах пакета не вызывается. · mongodb
// ext-mongodb 1.x, историческая сигнатура
final public function MongoDB\Driver\ReadPreference::getMode(): intВызов и параметры
В старом драйвере метод без аргументов вызывался на объекте ReadPreference, например при сохранении режима в конфигурацию.
Возвращаемое значение
Возвращал одно из целых значений режима. Соответствие 1 → primary, 5 → primaryPreferred, 2 → secondary, 6 → secondaryPreferred, 10 → nearest. Современный getModeString() возвращает строку.
Ошибки и границы применения
До удаления API при ошибочных аргументах документация указывала InvalidArgumentException. В драйвере 2.x прямой вызов отсутствующего метода приводит к PHP Error. Безопасная миграция проверяет прежний формат, переводит только известные значения и использует строковый конструктор.
Версии
Введён в 1.0.0, устарел в 1.20.0, удалён в 2.0.0. Исторический getter в программах пакета не вызывается.
Миграция сохранённой конфигурации
$present = method_exists(ReadPreference::class, 'getMode');
$route = new ReadPreference('secondaryPreferred'); // строка получена из таблицы для прежнего числа 6На 2.5.5 present=false, после преобразования известного значения загрузится версия 4. Неизвестное значение 77 останется на разбор.
Открыть исходные данные, программу и её результат
Исправить журнал нового обработчика
$configured = $route->getModeString();
$server = $cursor->getServer();Современная строка secondaryPreferred стала читаемой для оператора. Адрес и роль ответившего узла берутся из курсора отдельно.
Открыть исходные данные, программу и её результат
Дальше можно открыть Современный getModeString() · Строковый конструктор.
MongoDB\Driver\ReadPreference::getHedgeПроверить параметр hedge в наследованной конфигурации.
Добавлен в 1.8.0. Шардированный сервер MongoDB 8.0 объявил hedged reads устаревшими и перестал применять их по умолчанию для nearest. В исходниках ext-mongodb 2.5.5 deprecated помечены и метод getHedge(), и свойство hedge. · mongodb
final public function MongoDB\Driver\ReadPreference::getHedge(): ?objectВызов и параметры
Без аргументов. Вызов читает настройку объекта. Исторический параметр hedge при конструировании задавался документом, например enabled=false, для непервичного режима.
Возвращаемое значение
При наличии опции возвращает объект с её полями. При отсутствии возвращает null. Явно заданное enabled=false является значением поля объекта. Прямой вызов в 2.5.5 вызывает сообщение об устаревшем API и по-прежнему возвращает результат.
Ошибки и границы применения
Опция не измеряет задержку и не свидетельствует о выполнении параллельных запросов. Неверное сочетание hedge с primary отклоняется конструктором. PHP.net указывает InvalidArgumentException при разборе некорректных аргументов метода. В новом коде создавайте нужный маршрут без устаревшей опции.
Версии
Добавлен в 1.8.0. Шардированный сервер MongoDB 8.0 объявил hedged reads устаревшими и перестал применять их по умолчанию для nearest. В исходниках ext-mongodb 2.5.5 deprecated помечены и метод getHedge(), и свойство hedge.
Разобрать сохранённый флаг при переносе
$option = $historical->getHedge();
$enabled = $option?->enabled;Из старого профиля получаем false, из нового — null. Полный пример фиксирует адресные предупреждения PHP и проверяет карточку выпуска новым запросом.
Открыть исходные данные, программу и её результат
Перенести выбор площадки без hedge
$route = new ReadPreference('nearest', [['dc' => 'east'], []]);
$stored = $route->bsonSerialize();
$hasLegacyOption = property_exists($stored, 'hedge');Второй набор тегов оставляет маршрут к доступному узлу. Проверять отсутствие поля можно в описании объекта, не вызывая устаревший getter в новом обработчике.
Открыть исходные данные, программу и её результат
Дальше можно открыть Настройки выбора узла · Форма документа ReadPreference.
Источники и обсуждения
- class.mongodb-driver-readconcern
- class.mongodb-driver-readpreference
- class.mongodb-driver-writeconcern
- mongodb-driver-readconcern.bsonserialize
- mongodb-driver-readpreference.bsonserialize
- mongodb-driver-readpreference.gethedge
- mongodb-driver-readpreference.getmode
- mongodb-driver-writeconcern.bsonserialize
- Stub ReadPreference 2.5.5
- Реализация ReadPreference 2.5.5
- Stub ReadConcern 2.5.5
- Stub WriteConcern 2.5.5
- Выбор сервера
- Hedged reads
- Write concern
- Read concern
- Query::__construct
- ReadPreference::__construct
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


