可以选择在雄辩的资源集合中包含关系



我希望在集合 api 端点上选择性地加载关系

终点将是这样的

http://127.0.0.1:8000/api/posts/?include=comments includes comments with posts and I can add more using comma, like
http://127.0.0.1:8000/api/posts/?include=comments,images

但是当我不传递这些查询参数时,它应该只返回端点http://127.0.0.1:8000/api/postspostshttp://127.0.0.1:8000/api/posts?page=10

请求查询筛选器

<?php
namespace AppHttpResources;
use IlluminateHttpRequest;
class RequestQueryFilter
{
public function attach($resource, Request $request = null)
{
$request = $request ?? request();
return tap($resource, function($resource) use($request) {
$this->getRequestIncludes($request)->each(function($include) use($resource) {
$resource->load($include);
});
});
}
protected function getRequestIncludes(Request $request)
{
// return collect(data_get($request->input(), 'include', [])); //single relationship
return collect(array_map('trim', explode(',', data_get($request->input(), 'include', [])))); //multiple relationships
}
}

帮助程序中

<?php
if ( ! function_exists('filter') ) {
function filter($attach) 
{
return app('filter')->attach($attach);
}
}
?>

后控制器

public funciton index(Request $request) {
$posts = Post::all();
return new PostCollection(filter($posts));
}

在后期收藏

return [
'data' => $this->collection->transform(function($post){
return [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body,
'comments' =>  new CommentCollection($post->whenLoaded('comments')),
'images' =>  new ImageCollection($post->whenLoaded('images'))
];
}),
];

展示

调用未定义的方法 App\Models\Post::whenLoaded((", 但是如果我使用单个模型资源,它工作正常。

更新:原因:- 收集后转换给出

Collection gives 
Post {#363
#guarded: array:1 [
0 => "id"
]
#connection: "mysql"
#table: "posts"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:9 [

但发布资源$this给出

Post {#344
+resource: Post {#343
#guarded: array:1 [
0 => "id"
]
#connection: "mysql"
#table: "posts"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:9 [

现在将后收集$post转换为后资源

'data' => $this->collection->transform(function($post) use ($request) {
$post = new PostResource($post);
dd($post);

使用这个

'comments' => new CommentCollection($post->whenLoaded('comments')),将始终返回评论,即使include中没有comments

$post->relationLoaded('comments')

始终返回 true。

我不知道这是设计使然还是错误。我最好的猜测是它不适用于集合whenLoaded($relation)因为它是资源类的方法,而不是模型本身。但作为解决方法,以下内容应该有效:

return [
'data' => $this->collection->transform(function ($post) {
return [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body,
'comments' => $this->when($post->relationLoaded('comments'), function () use ($post) {
return new CommentCollection($post->comments);
}),
'images' => $this->when($post->relationLoaded('images'), function () use ($post) {
return new ImageCollection($post->images);
})
];
}),
];

由于您总是得到$post->relationLoaded('comments')返回true,我的建议是在基本模型上创建一个新方法(或者如果您没有,则创建Post模型(,该方法不仅可以检查加载状态,还可以检查关系的内容:

public function relationLoadedAndNotEmpty(string $relation): bool
{
return $this->relationLoaded($relation) && 
$this->getRelation($relation) instanceof IlluminateSupportCollection &&
$this->getRelation($relation)->isNotEmpty();
}

按照上述建议在资源中使用此方法而不是"$post->relationLoaded('comments'("应该会给你所需的结果,因为它还可以避免在集合为空时打印属性。

最新更新