向雄辩的资源添加过滤器以有条件地附加关系 [英] Adding filter to eloquent resource to attach relationship conditionally

查看:92
本文介绍了向雄辩的资源添加过滤器以有条件地附加关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Laravel 5.8 PHP 7.4

Laravel 5.8 PHP 7.4

我想像这样有条件地加载关系

I want to load the relationships conditionally like

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

如果存在查询参数,则只有该参数才能加载带有帖子的评论,或者仅加载帖子/帖子

If the query parameter is there, only then it should load comments with posts or it should load only posts/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中

in 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

A work around will be 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()调用进行懒惰的渴望加载

Lazy Eager加载完成的最终结果与Laravel中的with()相同,但是不是自动完成的. 例如:

Lazy Eager Loading using the load() call

The Lazy Eager Loading accomplishes the same end results as with() in Laravel, however, not automatically. For example:

?include=comments

// Get all posts.
$posts = Post::without('comments')->all();

if (request('include') == 'comments')) {
    $posts->load('comments');
}

return PostResource::collection($posts);

或者,您可以要求include查询字符串为数组:

Alternativelly, you could require the include query string to be an array:

?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().

The call without() is only required in case you defined your model to automatically eager load the relationships you want to conditionally load.

public function toArray($request) {
    $data = [...];

    foreach ($this->relations as $name => $relation)
    {
        $data[$name] = $relation;
    }

    return $data;
}

这篇关于向雄辩的资源添加过滤器以有条件地附加关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆