判断用户是否对帖子或回复进行点赞时,如何避免 N+1 问题?

您好,我实现了一个点赞模型,请问在对每个帖子或者回复判断是否点赞得时候,如何避免N+1问题?

    public function index(Request $request, Sentence $sentence)
    {
        $query = $sentence->query();
        if ($schoolID = $request->school_id) {
            $query->where('school_id', $schoolID);
        }
        $query->recent();
        $sentences = $query->paginate(20);
        return $this->response->paginator($sentences, new SentenceTransformer());
    }
    public function transform(Sentence $sentence)
    {
        return [
            'id' => (int)$sentence->id,
            'content' => $sentence->content,
            'user_id' => (int) $sentence->user_id,
            'school_id' => (int) $sentence->school_id,
            'reply_count' => (int) $sentence->reply_count,
            'like_count' => (int) $sentence->like_count,
            'is_liked'=>Like::where([['type', 'sentence'], ['type_id',$sentence->id],['user_id',Auth::guard('api')->id()]])->first()?true:false,
            'created_at' => $sentence->created_at->diffForHumans(),
            'updated_at' => $sentence->updated_at->toDateTimeString(),
        ];
    }
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

可以参考 5.5 的 resource 写法:

 public function index(Request $request, Sentence $sentence)
{
        $query = $sentence->query();
        if ($schoolID = $request->school_id) {
            $query->where('school_id', $schoolID);
        }
        $query->recent();
        // 预加载出 like 数据
        $query->load(['like' => function ($query) {
           // 过滤条件 
            $query->where();
        }]);
        $sentences = $query->paginate(20);
        return $this->response->paginator($sentences, new SentenceTransformer());
}

增加一个方法

public function transform(Sentence $sentence)
{
        return [
            'id' => (int)$sentence->id,
            'content' => $sentence->content,
            'user_id' => (int) $sentence->user_id,
            'school_id' => (int) $sentence->school_id,
            'reply_count' => (int) $sentence->reply_count,
            'like_count' => (int) $sentence->like_count,
            'is_liked'=> $this->whenLoaded('like', function () use ($sentence) {
                  // 具体是什么关系,自己判断一下, collection 使用 isNotEmpty() 
                  return $sentence->like;
           });
            'created_at' => $sentence->created_at->diffForHumans(),
            'updated_at' => $sentence->updated_at->toDateTimeString(),
        ];
}

protected function whenLoaded($relationship, $value = null, $default = null)
{
        if (func_num_args() < 3) {
            $default = new MissingValue;
        }

        if (! $this->resource->relationLoaded($relationship)) {
            return $default;
        }

        if (func_num_args() === 1) {
            return $this->resource->{$relationship};
        }

        if ($this->resource->{$relationship} === null) {
            return null;
        }

        return value($value);
}
4年前 评论
讨论数量: 7

可以参考 5.5 的 resource 写法:

 public function index(Request $request, Sentence $sentence)
{
        $query = $sentence->query();
        if ($schoolID = $request->school_id) {
            $query->where('school_id', $schoolID);
        }
        $query->recent();
        // 预加载出 like 数据
        $query->load(['like' => function ($query) {
           // 过滤条件 
            $query->where();
        }]);
        $sentences = $query->paginate(20);
        return $this->response->paginator($sentences, new SentenceTransformer());
}

增加一个方法

public function transform(Sentence $sentence)
{
        return [
            'id' => (int)$sentence->id,
            'content' => $sentence->content,
            'user_id' => (int) $sentence->user_id,
            'school_id' => (int) $sentence->school_id,
            'reply_count' => (int) $sentence->reply_count,
            'like_count' => (int) $sentence->like_count,
            'is_liked'=> $this->whenLoaded('like', function () use ($sentence) {
                  // 具体是什么关系,自己判断一下, collection 使用 isNotEmpty() 
                  return $sentence->like;
           });
            'created_at' => $sentence->created_at->diffForHumans(),
            'updated_at' => $sentence->updated_at->toDateTimeString(),
        ];
}

protected function whenLoaded($relationship, $value = null, $default = null)
{
        if (func_num_args() < 3) {
            $default = new MissingValue;
        }

        if (! $this->resource->relationLoaded($relationship)) {
            return $default;
        }

        if (func_num_args() === 1) {
            return $this->resource->{$relationship};
        }

        if ($this->resource->{$relationship} === null) {
            return null;
        }

        return value($value);
}
4年前 评论

@DavidNineRoc

"Method Illuminate\Database\Query\Builder::load does not exist.

query方法不能预加载吗

4年前 评论

@wangjiu 你先看一下你定义好模型之间的关联关系了没有

4年前 评论

@DavidNineRoc 您好,重新定义关联之后查询正常了,但是我使用的是dingo的transformer,貌似不支持whenloaded方法,请问应该怎么处理

4年前 评论

file
所以叫你增加一个方法

4年前 评论

@DavidNineRoc 也试过增加方法,提示MissingValue缺失 - -

4年前 评论

@wangjiu 学会查看错误,这是因为没有引入命名空间

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!