【问题标题】:How to attach data from one array to another in php如何在php中将数据从一个数组附加到另​​一个数组
【发布时间】:2018-11-25 21:04:31
【问题描述】:

我正在构建一个 [post, cmets] 项目,其中帖子详细信息存储在帖子表中,评论详细信息存储在 cmets 表中。该项目是在 Laravel(Php) 中生成的。这是一段代码。

//get data from Post table
$posts = $this->postsRepo->getAllPosts();
//get data from comments table
$comments = $this->commentRepo->getAllComments();
print_r($posts);
print_r($comments);

post 表的结果

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [post_text] => This is a test post
        )
)
    [1] => stdClass Object
        (
            [id] => 2
            [post_text] => This is another test
        )
)

cmets 表的结果

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [post_id] => 1
            [comments_text] => This is a test comment 1
        )
    [1] => stdClass Object
        (
            [id] => 2
            [post_id] => 1
            [comments_text] => This is a test comment 2
        )
)

现在我想要类似的结果

Array
(
    [0] => stdClass Object
    (
        [id] => 1
        [post_title] => This is a test post         
        [comments] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => 1
                        [post_id] => 1
                        [comment_text] => This is a test comment 1
                    )

                [1] => stdClass Object
                    (
                        [id] => 2
                        [post_id] => 1
                        [comment_text] => This is a test comment 2 
                    )
            )
        )
    )
    [1] => stdClass Object
    (
        [id] => 2
        [post_title] => This is another test
        [comments] => Array()
    )

)

我使用了以下技术,它正在工作

foreach ($posts as $postIndex => $post) {
    foreach ($comments as $commentIndex => $comment) {
        if($post->id == $comment->post_id) {
            $posts[$postIndex]->comments[] = $comment;
        }
    }
}

还有另一种方法,例如在 post for 循环中运行 cmets。我会将 post_id 发送到 cmets 表。但是随着数据的增加,这种技术会很慢

有人可以提出更好的技术来解决这个问题吗? 另外,我使用 Repository 设计模式来获取帖子和 cmets

【问题讨论】:

  • 为什么不使用 laravel 关系? laravel.com/docs/5.6/eloquent-relationships
  • 在您的 Post Model 中定义关系并命名 cmets 更改您的查询 PostModel::with('cmets')->get();
  • 我没有使用 Eloquent。使用简单的数据库查询
  • 你使用的是什么版本的 PHP?
  • 放弃 repo 设计模式并使用 eloquent。它做同样的事情,并且已经为您提供了执行此操作的代码。

标签: php arrays laravel for-loop


【解决方案1】:

有几种方法可以做到这一点,具体取决于您使用的 PHP 版本(尽管 1 将始终有效)。主要原则是通过 ID 索引其中一个数组,这样您就可以使用索引来设置值,而不是循环遍历两个数组。由于每个帖子可以有多个 cmets,因此通过 ID 索引帖子并循环遍历 cmets 将它们添加到正确的帖子中似乎更容易......

$posts = [
    (object)[
        "id" => 1,
        "post_text" => "This is a test post"
    ],
    (object)[
        "id" => 2,
        "post_text" => "This is another test"
    ]
];

$comments = [(object)
    [
        "id" => 1,
        "post_id" => 1,
        "comments_text" => "This is a test comment 1"
        ],
    (object)
    [
        "id" => 2,
        "post_id" => 1,
        "comments_text" => "This is a test comment 2"
        ]
    ];

$postIndex = array_column($posts, null, "id");   
//$postIndex = array_reduce($posts, function ($result, $post) { // PHP pre 7
//    $result[$post->id] = $post;
//    return $result;
//}, array());
foreach ( $comments as $comment )   {
    $postIndex[ $comment->post_id ]->comments[] = $comment;
}
echo "<pre>";
print_r($postIndex);

输出...

Array
(
    [1] => stdClass Object
        (
            [id] => 1
            [post_text] => This is a test post
            [comments] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 1
                            [post_id] => 1
                            [comments_text] => This is a test comment 1
                        )

                    [1] => stdClass Object
                        (
                            [id] => 2
                            [post_id] => 1
                            [comments_text] => This is a test comment 2
                        )

                )

        )

    [2] => stdClass Object
        (
            [id] => 2
            [post_text] => This is another test
        )

)

唯一的区别是,从 PHP 7.0 开始,您可以将 array_column() 与对象数组一起使用。在此之前,您必须手动进行转换。

【讨论】:

  • 我认为你的评论 id 2 是在错误的地方。我相信 cmets 数组中的“post_id”表示它与哪个帖子有关
  • @Andreas,谢谢 - 我错了...只是测试看看是否有人在看 >;)
  • 我还有 2 张桌子(点赞、评论点赞)。想用帖子数组(就像我们连接 cmets)和 cmets 数组中的 cmets 连接帖子
  • 附加了一张表格。现在表结构将像这样用户->帖子->评论。为此要使用什么?请帮帮我
  • 对不起,我没有时间解决这个问题,直到明天。到目前为止,您最好对代码提出一个新问题以及您想要实现的目标。
【解决方案2】:

你最好使用雄辩的关系...... 但要回答您当前案例的问题,如果您需要以 php 方式完成此操作。

// for all the post of the posts array
    foreach ($posts as $key => $value) {

        // get comments which only belongs to the post
        $post_comments = [];
        foreach ($comments as $comment) {

            if ($comment['post_id'] == $value['id']) {
                array_push($post_comments, $comment);
            }
        }

        // add a new attribute (comments) to each post
        // set created comments array of the post
        $post[$key]['comments'] = $post_comments;
    }

【讨论】:

    【解决方案3】:

    如果您循环发布帖子,则可以使用 array_intersect 和 array_intersect_key。
    这意味着您只循环一个数组一次,但使用数组函数来获取正确的 cmets。
    这意味着数组必须是数组而不是对象。

    Foreach($posts as $key => $post){
        $matches = array_intersect(array_column($comments, "post_id"), [$post["id"]]);
        $new[$key][] = $post;
        $new[$key]["comments"][] = array_intersect_key($comments, $matches);
    }
    
    Var_dump($new);
    

    https://3v4l.org/eq20D

    【讨论】:

      猜你喜欢
      • 2016-09-21
      • 1970-01-01
      • 2020-10-06
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 1970-01-01
      • 2012-03-27
      相关资源
      最近更新 更多