【问题标题】:DB::raw convert to query builderDB::raw 转换为查询生成器
【发布时间】:2019-08-16 14:07:17
【问题描述】:

您能帮我将查询的原始部分转换为使用查询生成器吗?
我被困在了一起:

$profile = UserProfiles::select('id')->where('alias', $profileAlias)->first();

$dbRawMessagesCount = '
  (SELECT COUNT(pm.id) 
  FROM profile_messages pm 
  WHERE pm.to_profile_id='.$profile->id.' 
     AND pm.from_profile_id=profile_friend.id 
     AND pm.is_read=0) AS messages_count
';

$friends = ProfileFriend::select('profile_friend.*', DB::raw($dbRawMessagesCount))
    ->with('friendProfile')
    ->whereHas('ownerProfile', function ($query) use ($profile) {
        return $query->where('id', $profile->id);
    })
    ->orderBy('messages_count')
    ->paginate();

【问题讨论】:

  • 您能否将预期的结果解释清楚一点? :) 任何额外的上下文都会有所帮助。
  • 我想他得到了原始 SQL 并希望以查询生成器格式重写它。您会看到他通过 SQL 方法计算了一些消息,然后使用该字段来 orderBy

标签: laravel laravel-5 eloquent laravel-query-builder


【解决方案1】:

如果ProfileFriend 已经与ProfileMessages 建立了关系,则可以在查询中使用withCount() 将其重写为一个查询。

$friends = ProfileFriend::with('friendProfile')
    ->withCount(['profileMessages' => function($q) use($profile){
        $q->where('to_profile_id', $profile->id)->where('is_read', 0); 
        // No longer need 'from_profile_id' as it is already querying the relationship
    }])
    ->whereHas('ownerProfile', function ($query) use ($profile) {
        return $query->where('id', $profile->id);
    })
    ->paginate();

现在,如果您 dd($friends->first()) 您会注意到它有一个名为 profileMessages_count 的字段,它可以让您计算我假设的未读消息。

【讨论】:

  • 您的解决方案根据接收到的行计算消息,例如您收到 50 条未读消息作为集合,然后通过 php count 计算数组中的元素数。在原始问题中,注意通过 SQL 计算消息数,我想稍后按未读消息数排序,但在您的解决方案中,进一步按未读消息数排序是很成问题的? (没有循环接收的结果,尤其是在分页时)
  • 我不确定你在问什么。这会为模型添加一个包含关系计数的属性。
  • 如何按照提供的方式按照收到的计数排序?例如,我想根据消息的数量对结果 desc 进行排序,其余的根据姓氏排序
  • 因为它是模型上的一个属性,您可以使用集合方法sortByDesc('profileMessages_count')->sortBy('last_name') 以合理的方式对列表进行排序。任何有未读内容的消息都将位于列表顶部,然后列表的其余部分将按姓氏排序。
猜你喜欢
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 2020-07-09
  • 1970-01-01
  • 2019-03-09
  • 2021-08-07
  • 2015-07-21
相关资源
最近更新 更多