Как правильно пользоваться ресурсами в laravel?

Есть ресурс модели User, у которого есть несколько специальностей (specialities)
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'specialities' => SpecialityResource::collection($this->activeSpecialities),
    ];
}


Ресурс специальности, в которой имеется ресурс для юзера.
public function toArray($request)
{
    return [
        'user' => UserResource::make($this->user),
        'special_price' => $this->special_price,
    ];
}


В итоге получаю рекурсию.
Где-то неверно понимаю концепцию ресурсов, но не соображу в чем именно.
  • Вопрос задан
  • 937 просмотров
Решения вопроса 1
slowdream
@slowdream Автор вопроса
public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'specialities' => SpecialityResource::collection($this->whenLoaded('activeSpecialities')),
    ];
}


public function toArray($request)
{
    return [
        'user' => UserResource::make($this->whenLoaded('user')),
        'special_price' => $this->special_price,
    ];
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Kostik_1993
PHP Backend Developer, Laravel, Yii, Vue, Node.js
Нужно делать проверку на наличие реляций. Ну а из наличие будет зависеть от вашего запроса, если вы вызовите запрос with(‘user’) то они выведутся, если без то не выведется, ну или делать разные ресурсы ещё можно
Ответ написан
gzhegow
@gzhegow
Думал, стану умнее, когда адаптируюсь, но нет
Так это у тебя ясно написано запустить маппер для дочерних обьектов внутри которых запустить маппер для родительских. Ну вот тебе и рекурсия, нет?

Ресурс это считай array_map();
Метод collection() это просто array_map() для array_map()

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

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

Кроме того маааленький сюрприз - у тебя идет обращение к связанной модели, а поскольку скорее всего ты до этого не сделал with('specialitiesResource') то оно у тебя еще и запрос к базе в рекурсии делает

И второй сюрприз, еще поменьше, когда ты маппишь коллекцию юзеров, то он для каждого юзера делает запрос в базу для каждой специальности. Дважды n+1 query в рекурсии
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы