Laravel 5.6 - передать дополнительные параметры в API Resource? - PullRequest
0 голосов
/ 01 июня 2018

Ресурс API Laravel может быть отдельным ресурсом или коллекцией.В некоторых случаях дополнительные параметры необходимо передать в ресурс / коллекцию от контроллера.Ниже приведен простой пример, демонстрирующий проблему с использованием User в качестве отдельного ресурса / ресурса коллекции и настраиваемого параметра $apple, который передается ресурсу для вывода.Проблема может быть замечена в окончательном Output (Collection) ниже, где для значения fruit мы получаем неправильное значение banana для первого пользователя вместо правильного значения apple (которое получают все другие пользователи),Он отлично работает для одного выхода, но не для коллекции.См. Ниже:

Контроллер с UserResource (Single)

$user = User::first();
return new UserResource($user, $apple = true); // $apple param passed

Контроллер с UserResource (Collection)

$users = User::limit(3)->get();
return UserResource::collection($users, $apple = true); // $apple param passed

UserResource

<?php

namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource {
    private $apple;

    public function __construct($resource, $apple = false) {
        // Ensure we call the parent constructor
        parent::__construct($resource);
        $this->resource = $resource;
        $this->apple = $apple; // $apple param passed
    }

    public function toArray($request) {
        return [
            'id'     => (int) $this->id, 
            'name'   => $this->name,
            'fruit'  => $this->apple ? 'apple' : 'banana',
        ];
    }
}

Выход (одиночный)

{
    "data": {
        "id": 1,
        "name": "Peter",
        "fruit": "apple" // correct param!
    }
}

Выход (сборник)

{
    "data": [
        {
            "id": 1,
            "name": "Peter",
            "fruit": "banana" // INCORRECT param!
        },
        {
            "id": 2,
            "name": "Lois",
            "fruit": "apple" // correct param!
        },
        {
            "id": 3,
            "name": "Brian",
            "fruit": "apple" // correct param!
        }
    ]
}

Обратите внимание, что это всего лишь пример, это может быть любое количество случайных параметров (не связанных с коллекцией User, но они должны быть переданы для логики вывода), например одно значение read_at отметка времени издругую таблицу, которую я хочу передать один раз, и выполнить некоторую логику для нее в коллекции ресурсов перед выводом (например, сравнение с пользовательской меткой времени), или другие параметры, переданные для дополнительной логики if/else, которая должна быть выполнена в файле ресурсов в целом дляманипулировать выводом коллекции.Как это можно сделать?

Ответы [ 3 ]

0 голосов
/ 06 августа 2018

У меня работал следующий подход:

UserResource

class UserResource extends Resource{

    protected $foo;

    public function foo($value){
        $this->foo = $value;
        return $this;
    }

    public function toArray($request){
        return [
            'id' => $this->id,
            'name' => $this->name,
            'foo' => $this->foo,
         ];
    }

    public static function collection($resource){
        return new UserResourceCollection($resource);
    }
}

UserCollection

class UserResourceCollection extends ResourceCollection{

    protected $foo;

    public function foo($value){
        $this->foo = $value;
        return $this;
    }

    public function toArray($request){
        return $this->collection->map(function(UserResource $resource) use($request){
            return $resource->foo($this->foo)->toArray($request);
    })->all();

        // or use HigherOrderCollectionProxy
        // return $this->collection->each->foo($this->foo)->map->toArray($request)->all()

        // or simple
        // $this->collection->each->foo($this->foo);
        // return parent::toArray($request);
    }
}

Различные способы передачи дополнительного параметра

(new UserResource($user))->foo('bar');
(new UserResourceCollection($user))->foo('bar');

UserResource::make($user)->foo('bar');
UserResourceCollection::make($users)->foo('bar');
UserResource::collection($users)->foo('bar');
0 голосов
/ 17 октября 2018

Для работы с Laravel 5.7 я внес некоторые изменения в отношении ответа Вонки

UserResource

class UserResource extends Resource{

    protected $foo;

    public function foo($value){
        $this->foo = $value;
        return $this;
    }

    public function toArray($request){
        return [
            'id' => $this->id,
            'name' => $this->name,
            'foo' => $this->foo,
         ];
    }

    public static function collection($resource){
        return new UserResourceCollection($resource, get_called_class());
    }
}

UserCollection

class UserResourceCollection extends AnonymousResourceCollection {

    protected $foo;

    public function foo($value){
        $this->foo = $value;
        return $this;
    }

    public function toArray($request){
        return $this->collection->map(function(UserResource $resource) use($request){
            return $resource->foo($this->foo)->toArray($request);
    })->all();

    }
}
0 голосов
/ 05 августа 2018

Вы можете передать дополнительные параметры как часть вызова конечной точке API.Затем вы можете получить доступ к параметрам с помощью объекта $ request (для вашего примера) в UserResource.

Например, если вы вызываете конечную точку из клиента, такого как веб-браузер, axios и т. Д., Используя что-то вроде:

http://localhost:3000/api/users?apple=true

, это сделает параметр apple со значением trueдоступно в контроллере.Без каких-либо других действий с вашей стороны он также будет доступен в массиве ToArray ($ request) UserResource.Вы можете получить к нему доступ, аналогично:

public function toArray($request) {
      $isApple = $request->apple;

        return [
            'id'     => (int) $this->id, 
            'name'   => $this->name,
            'fruit'  => $isApple ? 'apple' : 'banana',
        ];
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...