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