wake-up-neo.net

Laravel 5.6 - Zusätzliche Parameter an API Resource übergeben?

Eine Laravel API-Ressource kann entweder eine einzelne Ressource oder eine Sammlung sein. In einigen Fällen müssen zusätzliche Parameter vom Controller an die Ressource/Sammlung übergeben werden. Im Folgenden finden Sie ein einfaches Beispiel, das das Problem mit User als Einzel-/Erfassungsressource und einem benutzerdefinierten Parameter $Apple veranschaulicht, der zur Ausgabe an die Ressource übergeben wird. Das Problem ist in der letzten Output (Collection) unten zu sehen, in der für den Wert fruit anstelle des korrekten Werts banana (den alle anderen Benutzer erhalten) für den ersten Benutzer der falsche Wert Apple angegeben wird. Es funktioniert perfekt für die einzelne Ausgabe, nur nicht für die Sammlung. Siehe unten:

Controller mit UserResource (Single)

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

Controller mit UserResource (Sammlung)

$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',
        ];
    }
}

Ausgabe (einzeln)

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

Ausgabe (Sammlung)

{
    "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!
        }
    ]
}

Beachten Sie, dass dies nur ein Beispiel ist. Es kann sich um eine beliebige Anzahl zufälliger Parameter handeln (die nicht mit der Auflistung User zusammenhängen, jedoch für die Ausgabelogik übergeben werden müssen), z. B. einen einzelnen Wert read_at timestamp aus einer anderen Tabelle, die ich einmal übergeben möchte. Führen Sie vor der Ausgabe eine Logik in der Ressourcensammlung aus (z. B. einen Vergleich mit einem Benutzerzeitstempel), oder übergeben Sie andere Parameter, damit die zusätzliche Logik if/else im Allgemeinen in der Ressourcendatei ausgeführt wird, um die Ausgabe der Sammlung zu bearbeiten. Wie geht das?

3
Wonka

Der folgende Ansatz hat für mich funktioniert:

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);
    }
}

Verschiedene Möglichkeiten, den zusätzlichen Parameter zu übergeben

(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');
8
Wonka

Sie können die zusätzlichen Parameter als Teil des Aufrufs an den API-Endpunkt übergeben. Sie können dann mit dem $ request-Objekt (für Ihr Beispiel) in der UserResource auf die Parameter zugreifen. 

Wenn Sie beispielsweise den Endpunkt von einem Client aus aufrufen, z. B. einen Webbrowser, Axios usw., verwenden Sie Folgendes:

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

dadurch wird der Parameter Apple mit dem Wert true im Controller verfügbar. Ohne weitere Aktion Ihrerseits ist es dann auch im toArray ($ request) der UserResource verfügbar. Sie können wie folgt darauf zugreifen:

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

        return [
            'id'     => (int) $this->id, 
            'name'   => $this->name,
            'fruit'  => $isApple ? 'Apple' : 'banana',
        ];
    }
0
SnapShot

Um mit Laravel 5.7 zu arbeiten, habe ich einige Änderungen in Bezug auf Wonkas Antwort vorgenommen. _

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
Gabriel