php - 向 Eloquent 资源添加过滤器以有条件地附加关系

标签 php laravel eloquent eloquent-relationship laravel-eloquent-resource

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/

相关文章:

php - 使用 PHP bcrypt(在 Laravel Hash::make 中)时是否有最大输入长度?

php - 如何使用数据库 laravel 背包中的数据更改标题

mysql - 我可以在 laravel 数据库查询中使用 if 条件吗?

laravel - 使用 Laravel Eloquent 创建嵌套的 OR 条件

php - 在 1 个查询中对 Sum & Count 列求和或使用 PHP?

php - 通过 PHP 连接到 Google AdSense API

php - 在移动设备上选择输入文本时,不将输入文本居中

php - 在 Laravel/Homestead 中映射文件夹和站点

laravel - CORS 请求未成功

php - Laravel hasMany 关系计数帖子上的喜欢和评论数