Laravel 5.8 PHP 7.4
我想有条件地加载关系,例如
http://127.0.0.1:8000/api/posts
和
http://127.0.0.1:8000/api/posts/1 are my end points now, I want to load comments like
http://127.0.0.1:8000/api/posts/?include=comments
和
http://127.0.0.1:8000/api/posts/1/?include=comments
如果查询参数存在,只有这样它才应该加载带有帖子的评论,或者应该只加载帖子/帖子
我是通过引用 blog post 来做到这一点的
现在,RequestQueryFilter
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
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);
}
}
?>
在PostController中
public funciton show(Request $request, Post $post) {
return new PostResource(filter($post));
}
但是当我尝试检索时
http://127.0.0.1:8000/api/posts/1/?include=comments getting no comments, with no error in log
解决方法是 PostResource
public function toArray($request)
{
// return parent::toArray($request);
$data = [
'id' => $this->id,
'name' => $this->title,
'body' => $this->content,
];
$filter = $request->query->get('include', '');
if($filter){
$data[$filter] = $this->resource->$filter;
}
return $data;
}
最佳答案
I want to load the relationships conditionally like
使用 load()
调用进行延迟预加载
延迟预加载实现与 Laravel 中的 with()
相同的最终结果,但不是自动实现的。 例如:
?include=comments
// Get all posts.
$posts = Post::without('comments')->all();
if (request('include') == 'comments')) {
$posts->load('comments');
}
return PostResource::collection($posts);
或者,您可以要求 include
查询字符串是一个数组:
?include[]=comments&include[]=tags
// Validate the names against a set of allowed names beforehand, so there's no error.
$posts = Post::without(request('includes'))->all();
foreach (request('includes') as $include) {
$posts->load($include);
}
return PostResource::collection($posts);
仅当您将模型定义为自动预先加载您想要有条件加载的关系时,才需要调用 without()
。
在 Controller 中过滤所有数据后,只需确保在 PostResource
中仅显示加载的关系
public function toArray($request) {
$data = [...];
foreach ($this->relations as $name => $relation)
{
$data[$name] = $relation;
}
return $data;
}
关于php - 向 Eloquent 资源添加过滤器以有条件地附加关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57478314/