首页 文章

Laravel 5.6 - 将其他参数传递给API资源?

提问于
浏览
1

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

Controller with UserResource (Single)

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

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

Output (Single)

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

Output (Collection)

{
    "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 传递的其他参数通常用于操纵集合的输出 . 如何才能做到这一点?

4 回答

  • 0

    以下方法对我有用:

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

    Different ways to pass the additional parameter

    (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

    您没有添加任何条件来过滤where子句中的数据 .

    尝试如下

    $apple = true;
    $q= new User;
    if($apple){
       $q = where('fruit','apple');
    }
    $users = $q->limit(3)->get();
    return UserResource::collection($users, $apple = true); // $apple param passed
    

    无需传递 $apple 并进一步处理

  • 4

    您可以将额外参数作为调用API终结点的一部分传递 . 然后,您可以使用UserResource中的$ request对象(对于您的示例)访问参数 .

    例如,如果您使用以下内容从客户端(如Web浏览器,axios等)调用 endpoints :

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

    这将使控制器中的参数apple值为true . 在您没有任何其他操作的情况下,它也可以在UserResource的toArray($ request)中访问 . 您可以访问它类似于:

    public function toArray($request) {
          $isApple = $request->apple;
    
            return [
                'id'     => (int) $this->id, 
                'name'   => $this->name,
                'fruit'  => $isApple ? 'apple' : 'banana',
            ];
        }
    
  • 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();
    
        }
    }
    

相关问题