@Metus
Программист

Что должен возвращать Laravel Repository — объекты или массивы?

Здравствуйте!

При работе с Laravel и попыткой использовать репозитории возникла следующая дилемма.

Большинство интернет ресурсов и учебников предполагают следующий вариант репозиториев:
<?php
class UserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all();
    }
}


Тем не менее, в книге создателя фреймворка "From Apprentice To Artisan" (а также некоторых других источниках) имеется следующий вариант:
<?php
class UserRepository implements UserRepositoryInterface
{
    public function all()
    {
        return User::all()->toArray();
    }
}


В первом случае репозиторий возвращает объекты Eloquent (точнее, обёртку над ними), во втором - они все преобразовываются в массивы.
FormBuilder работает корректно и с моделями, и с массивами.

В обоих случаях мы можем выводить кастомные атрибуты.

В первом случае идёт привязка к самой реализации хранения (что, по сути, ломает всю концепцию репозиториев), во втором - нет.
В первом случае откровенное враньё, что мы просто так возьмём и сможем использовать другую БД. Мы сможем, но нам во время разработки придётся внимательно следить, чтобы не вызывать никакие методы, а в случае смены БД наполнять что-то вроде stdClass.

В первом случае мы всегда получаем объект со свойствами и методами (которые теряются в случае, если мы больше не хотим использовать Eloquent), во втором просто неизвестный массив (исправить это можно обёртками).

В первом случае мы можем получить запросы во время отрисовки представления строкой вида (которые потом может быть непросто найти)
<?php
$user->role->name;

Во втором такого не будет (что, в общем-то, хорошо) если мы только явно в репозитории не сделаем что-то вроде этого, т.е. все запросы исключительно в репозиториях:
<?php
User::with('role')->get()->toArray();
$user['role']['name']


В первом случае мы без проблем можем использовать вот такой код:
<?php
$repo->newInstance(); // вернёт новый созданный объект Eloquent
echo $repo->id;

Во втором при попытке сделать что-то аналогичное мы получим ошибку.
<?php
$repo->newInstance(); // новый созданный объект Eloquent будет преобразован к массиву
echo $repo['id']; // => error: undefined index

Eloquent вообще не заботится о том, имеются ли данные свойства в базе или нет, он просто хранит список переданных значений (через new, fill и т.д.) и их преобразовывает к массиву. Любой запрос свойства, для которого нет значения, вернёт null, даже если такого поле нет в базе. Это открытие было немного шокирующим.
Это можно решить следующим кодом:
<?php
array_get($repo, 'id');

Либо, опять же, использовать какие-то обёртки, а не возвращать массив.

Собственно вопрос!
Что используете вы и что, как вы считаете, стоит использовать? Первый способ, по сути, не тот репозиторий, о котором нам пытаются рассказать многие авторы книг по Laravel, хотя и более удобен, нежели массивы.
  • Вопрос задан
  • 3277 просмотров
Пригласить эксперта
Ответы на вопрос 1
vanchelo
@vanchelo
Я всегда использую объекты, так как люблю те возможности которые они предоставляют.
Обращение к свойству модели значительно симпатичнее чем к ключу массива + не требует проверки на существование свойства как в случае с ключом массива.

Предпочитаю первый вариант работы с объектами.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы