Laravel原始查询和包含模型关系

5
我试图通过子查询返回一篇带有点赞和踩数的文章。我可以使用原生查询来实现这一点。然而,这样做意味着我不能再访问文章模型的关系,例如评论。是否有更优雅的Eloquent方法,可以保留模型关系?或者我还有其他更好的方法吗?期待听到您的建议。
$post = DB::select(
        "SELECT post.*, 
        (SELECT COUNT(*) FROM posts_votes 
        WHERE type = 1 
        AND post_id = posts.id) 
        AS up_votes, 
        (SELECT COUNT(*) FROM posts_votes 
        WHERE type = 2 
        AND post_id = posts.id) 
        AS down_votes 
        FROM posts 
        INNER JOIN posts_votes ON posts.id = posts_votes.post_id
        WHERE posts.id = ?", [$id])[0];

使用 Posts::select->where(function($subquery) {}) - Alex Slipknot
1
你可以在 Eloquent 模型中使用 raw 方法,例如 post::raw("sql 查询")->with("关联")。 - Divyank Munjapara
3个回答

2

试试这个

Post::select('*')
->addSelect(DB::raw('
    (select count(*) 
    from posts_votes 
    where type = 1 
    and post_id = posts.id) 
    as up_votes
'))
->addSelect(DB::raw('
    (select count(*) 
    from posts_votes 
    where type = 2 
    and post_id = posts.id) 
    as down_votes
'))
->whereIn('id', $ids)
->get();

这对我很有效。正如@DivyankMunjapara所评论的那样,我只需在查询末尾添加->with('relation')即可。但是,我发现这种方法更像Eloquent。在我的情况下,我只需要将whereIn()更改为where,因为我只查询一个帖子。 - patskot
我有一个问题(也许我应该开另一个问题?)。使用上面的例子,我如何将“posts_votes”计数应用于“$posts->children()”? - patskot
1
@patskot,您只需将所有选择项添加到子元素中。 $posts->children()->select($all)->addSelect($upvotesquery)->addSelect($downvotequery)->get()。在这种情况下,我建议在您的Post模型上创建一个范围。例如,scopeUpDownVotes()。 - Tim de Wolf
创建一个可重用的模型作用域效果非常好!感谢您的帮助 :) - patskot

1
这是一个老问题,但当我在谷歌上搜索“Laravel关联原始查询”时,它是我得到的第一个结果,因此对于其他正在寻找相同内容的人可能很有用。
我设法通过以下方式解决:
$query = ""; //raw query goes here
$result = Model::fromQuery($query);
$result->load('relationship');

请确保您的自定义原始查询包含模型中指定的正确列,否则关系将始终返回 null。

在 Laravel 6.17.0 上进行了测试。


0
这是对我非常有效的方法:
Model::where('condition_one', 1)->doesntHave('RelationShip')->get();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接