Как сделать, чтобы ActiveRecord MongoDB отдавал модели, а не массив

Если ActiveRecord MongoDB отдает массивы вместо моделей, чаще всего причина в asArray(), использовании низкоуровневого запроса к коллекции или неправильной модели. Для Yii2 MongoDB ActiveRecord результат Model::find()->all() должен возвращать объекты модели, если вы не включали режим массивов

Модель должна наследоваться от yii\mongodb\ActiveRecord:

use yii\mongodb\ActiveRecord;

class Product extends ActiveRecord
{
    public static function collectionName()
    {
        return 'products';
    }

    public function attributes()
    {
        return ['_id', 'title', 'price'];
    }
}

Получение моделей:

$products = Product::find()
    ->where(['active' => true])
    ->all();

foreach ($products as $product) {
    echo $product->title;
}

Здесь $product должен быть объектом Product

Проверьте asArray

Если в запросе есть asArray(), результат будет массивом:

$products = Product::find()
    ->where(['active' => true])
    ->asArray()
    ->all();

Чтобы вернуть модели, уберите asArray() или явно выключите его:

$products = Product::find()
    ->where(['active' => true])
    ->asArray(false)
    ->all();

Не путайте ActiveRecord и collection

Если вы делаете запрос через коллекцию напрямую, результат будет ближе к массивам документов:

$rows = Yii::$app->mongodb
    ->getCollection('products')
    ->find(['active' => true]);

Для моделей используйте Product::find(), а не прямой доступ к коллекции

one и all

one() возвращает одну модель или null:

$product = Product::find()->where(['_id' => $id])->one();

all() возвращает массив моделей:

$products = Product::find()->all();

Важно: all() всегда возвращает PHP-массив как контейнер, но элементы внутри должны быть объектами модели. Если вы ожидаете «не массив вообще», используйте one() для одного документа

Как проверить тип

var_dump($products[0] instanceof Product);

Если результат true, ActiveRecord вернул модель. Если false, смотрите asArray, тип запроса и наследование класса

Что делать с агрегациями

Если вы используете aggregation через MongoDB collection, результат часто будет массивом данных, а не ActiveRecord-моделью. Это нормально: aggregation возвращает вычисленный результат, который может не совпадать со структурой модели

Если вам нужны именно модели, сначала получите id документов, а потом запросите их через ActiveRecord:

$ids = array_column($rows, '_id');

$models = Product::find()
    ->where(['_id' => $ids])
    ->all();

Так вы отделяете вычисления от загрузки моделей

Частые ошибки

Используют asArray

asArray() нужен для легкого результата без методов модели. Для объектов модели его убирают

Запрашивают коллекцию напрямую

Низкоуровневый доступ полезен для особых запросов, но он не обязан возвращать ActiveRecord-модели

Не описали attributes

В Yii2 MongoDB ActiveRecord нужно корректно описать атрибуты документа, с которыми работает модель

Путают массив моделей и массив полей

all() возвращает массив, но это может быть массив объектов. Проверяйте элемент, а не контейнер

Ждут модель от агрегированного результата

Если pipeline возвращает не обычный документ коллекции, ActiveRecord не сможет автоматически превратить его в полноценную модель. Для таких ответов используйте DTO или отдельную сборку данных

Что почитать дальше по MongoDB

Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x