Laravel 5.6 - 将附加参数传递给API资源?

时间:2018-06-01 07:30:34

标签: laravel-5 laravel-5.5 laravel-5.6

Laravel API Resource可以是单个资源,也可以是集合。在某些情况下,需要从控制器将其他参数传递给资源/集合。下面是一个简单的示例,演示了使用User作为单个/集合资源以及要传递给资源以进行输出的自定义$apple参数的问题。这个问题可以在下面的最后Output (Collection)中看到,对于fruit值,第一个用户的banana值不正确,而不是正确的apple值(所有其他用户获得)。它适用于单个输出,而不是集合。见下文:

使用UserResource的控制器(单个)

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

使用UserResource(集合)的控制器

$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传递的其他参数文件通常用于操作集合的输出。怎么办呢?

7 个答案:

答案 0 :(得分:11)

以下方法对我有用:

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

答案 1 :(得分:3)

这个简单的技巧在Laravel 5.8中对我有用:)

控制器

$user = User::find($user->id);
$user->access_token = $tokenResult->accessToken; // Add additional data
return new ProfileResource($user);

资源

public function toArray($request)
{
    return [
        'id'            => $this->id,
        'picture'       => $this->picture,
        'first_name'    => $this->first_name,
        'last_name'     => $this->last_name,
        'active'        => $this->active,
        'access_token'  => isset($this->access_token) ? $this->access_token : '', // Additional data
    ];
}

答案 2 :(得分:1)

您可以将额外的参数作为调用的一部分传递给API端点。然后,可以使用UserResource中的$ request对象(例如)访问参数。

例如,如果您使用以下方式从客户端(例如Web浏览器,axios等)调用端点,则

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

这将使控制器中具有true值的参数apple可用。然后,您无需执行任何其他操作,即可在UserResource的toArray($ request)中进行访问。您可以类似于以下方式访问它:

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

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

答案 3 :(得分:1)

这就是我在 Laravel 8 上的实现方式。



class PatientResource extends JsonResource
{

  private static $data;
  /**
   * Transform the resource into an array.
   *
   * @param \Illuminate\Http\Request $request
   * @return array
   */
  public function toArray($request)
  {
    //access $data
    //self::$data
    return [
      'id' => $this->id,
      'first_name' => $this->first_name,
      'middle_name' => $this->middle_name,
      'last_name' => $this->last_name,
      'contact_number' => $this->contact_number
    ];
  }

  //I made custom function that returns collection type
  public static function customCollection($resource, $data): \Illuminate\Http\Resources\Json\AnonymousResourceCollection
  {
   //you can add as many params as you want.
    self::$data = $data;
    return parent::collection($resource);
  }
}

然后在我的控制器上我调用了那个自定义函数。

$data = PatientResource::customCollection($query->get(),$medicines);

答案 4 :(得分:0)

要使用Laravel 5.7,我对Wonka's answer

进行了一些更改

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

    }
}

答案 5 :(得分:0)

我通过仅在{p>内检索$request->get('param')来解决了问题

public function toArray($request){ 

   $param = $request->get('param');

   ... 

} 

而不是通过资源传递参数。

答案 6 :(得分:0)

您可以使用laravel 8

附加存储功能

    return (UserResource::make(User::find($user->id)))
            ->additional([
                'message'=>[
                    ['user by name: '.$user->name.' created successfull.']
                ]
            ])->response()->setStatusCode(201);