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

#php #laravel #eloquent

#php #laravel #красноречивый

Вопрос:

Проблема

У меня есть модель, имеющая измененное отношение, и эти отношения разного типа возвращают совершенно разные ресурсы json. Итак, я пытаюсь найти способ разрешить правильный класс отношений и вернуть его с ресурсом базовой модели.

Например, если у меня есть комментарий и измененное отношение «commentable», содержащие экземпляры модели Car и Driver. Теперь, если я запрошу какой-нибудь комментарий, я смог бы вернуть правильный ответ json, сохраненный в CarResource или PeopleResource.

 {
    id: 1,
    text: 'A comment',
    commentable_type: 'Car', // could be car or driver
    commentable_data: {
        model: 'Ford',
        year: 2019
    },

    id: 2,
    text: 'An another comment',
    commentable_type: 'Driver',
    commentable_data: {
        name: 'Jon Doe',
        active: true
    },
}
  

Пытаюсь решить

Я попытался использовать следующее, но получил ошибку.

 public function toArray($request)
{
    $modelClass = app(__NAMESPACE__ . '\' . class_basename($this->commentable) . 'Resource');

    return [
        'id' => $this->id,
        'text' => $this->text,
        'commentable_type' => class_basename($this->commentable),
        'commentable_data' => new $modelClass($this->commentable),
    ];
}
  

Если разрешенный класс не существует, я, конечно, получаю

Исключение ReflectionException (-1)

Класс App Http Resources CarResource не существует

Но если класс существует, я получаю следующую ошибку

Исключение Illuminate Contracts Container BindingResolutionException

Разрешение неразрешимой зависимости [Параметр # 0 [ $resource ]] в классе IlluminateHttpResourcesJson JsonResource

Вопрос

Что вы думаете? Есть ли у вас какое-либо решение или рекомендации, например, как лучше управлять этим?

Ответ №1:

Хорошо, я нашел решение, копнув немного глубже в Laravel. Сервисный контейнер — мой друг. Как исключение BindingResolutionException говорит, что мне нужно передать $resource параметр распознавателю с помощью makeWith() функции.

 $modelClass = app()->makeWith(__NAMESPACE__ . '\' . class_basename($this->barcodable) . 'Resource', [
    'resource' => $this->barcodable
]);
  

Однако, пожалуйста, дайте мне знать, если у кого-нибудь есть какие-либо мысли об улучшении этого.