【问题标题】:Laravel: Nesting query join results in a sub arrayLaravel:嵌套查询连接导致子数组
【发布时间】:2017-05-31 02:59:03
【问题描述】:

注意请不要建议使用 Eloquent,这是专门针对 Laravel 查询构建器的。

出于性能原因,我们使用查询生成器从表中检索结果:

DB::table('posts')->get();

如果我们想在那个查询上加入一个关系:

DB:table('posts')
    ->leftJoin('comments', 'posts.id', '=', 'comments.post_id')
    ->get();

将结果合并到每个帖子的数组中:

[
    'id'                => 1,
    'title'             => 'My Blog Post',
    'content'           => '<h1>This is a post</h1><p>hello world</p>',
    'post_author'       => 'Billy',
    'comment'           => 'This is a comment',
    'comment_author'    => 'Andrew',
]

我们如何将连接的结果放入嵌套数组中?如:

[
    'id'                => 1,
    'title'             => 'My Blog Post',
    'content'           => '<h1>This is a post</h1><p>hello world</p>',
    'post_author'       => 'Billy',
    'comment'           => [
        'id'                => 22,
        'comment'           => 'This is a comment',
        'comment_author'    => 'Andrew',            
    ],
]

【问题讨论】:

  • 尝试定义适当的关系。
  • 关系仅用于 Eloquent 的情况。 Laravel 查询生成器不处理关系。 @SougataBose
  • 查询返回的格式有什么问题?
  • 我知道。如果你们有关系,那么这很容易做到。
  • @SougataBose 问题明确指出不要使用 Eloquent ......

标签: php mysql arrays laravel laravel-5


【解决方案1】:

不要认为没有 Eloquent 就可以开箱即用。

你可以走原始路线:

$results = DB:table('posts')
    ->leftJoin('comments', 'posts.id', '=', 'comments.post_id')
    ->select('posts.*', 'comments.*', 'comments.id as comments_id')
    ->get(); 

foreach($results as &$result) 
{ 
    $result['comment'] = [
        'id' => $result['comment_id'], 
        'comment' => $result['comment'], 
        'comment_author' => $result['comment_author']
    ]; 
    unset($result['comment_author'], $result['comment_id']);
}

【讨论】:

  • 我希望 eloquent 有一种更微妙的方式来处理结果,至少作为一种选择。
  • 您的解决方案没有将每个帖子的所有 cmets 分组为一个嵌套数组,实际上每个帖子会出现 N 次,当 N 是它的 cmets 数时。
  • 这会使查询变得非常慢,好像有超过 10000+ 个帖子,然后查询本身将需要几秒钟才能执行
【解决方案2】:

由于你使用的是 DB 外观而不是 Eloquent,并且不能使用内置的 with() 方法,你必须自己实现它:

$posts = DB::table('posts')->get()->toArray();
$comments = DB::table('comments')->get()->toArray();

foreach($posts as &$post)
{
    $post->comments = array_filter($comments, function($comment) use ($post) {
        return $comment->post_id === $post->id;
    });
}

return $posts;

如果你想摆脱 post_id 的 cmets 条目,你可以这样做:

$posts = DB::table('posts')->get()->toArray();
$comments = DB::table('comments')->get()->toArray();

foreach($posts as &$post)
{
    $comments = array_filter($comments, function($comment) use ($post) {
        return $comment->post_id === $post->id;
    });

    $post->comments = array_map(function ($comment) {
        unset($comment->id);
        return $comment;
    }, $comments);
}

return $posts;

(我猜运行时会类似于with(),因为毕竟MySql 不提供开箱即用的功能)。

【讨论】:

    猜你喜欢
    • 2014-01-31
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多