循环遍历后数组被覆盖

3

我正在尝试将SQL结果集中包含元素的对象推入数组中。我的代码如下:

$data = array();
$sql = "SELECT id,type,name,username FROM users";
foreach ($conn->query($sql) as $row) { 
    $this->set_id($row['id']);
    $this->set_type($row['type']);
    $this->set_username($row['username']);
    $this->set_password($row['password']);

    $data[] = $this;
}

我的结果集是正确的,但是在foreach循环结束后,我的数组单元格被来自最后一个记录集的值覆盖。例如,如果我有这些结果{1,'type1','user','pass'}{2,'type2','foo','bar'},当我在循环外部打印$data数组时,我只得到第二个结果集重复两次。我做错了什么?

2
每次循环更新 $this 的单个实例,然后将每个数组元素指向相同的 $this... 如果 $this 是您的模型,则需要为每个数组元素创建一个新实例。 - Mark Baker
4个回答

3
在实例方法内部,$this 总是指向当前类实例;在每次循环迭代时,您修改实例本身,然后将其添加到 $data 中;但在赋值时,不会创建副本,而是添加对同一实例的引用。
最终,您将获得一个具有相同对象的数组。
您需要在每次循环迭代时创建类的新实例:
foreach ($conn->query($sql) as $row) { 
    $obj = new self; // create new instance of ourselves

    $obj->set_id($row['id']);
    $obj->set_type($row['type']);
    $obj->set_username($row['username']);
    $obj->set_password($row['password']);

    $data[] = $obj;
}

这是一个个人建议,但我建议您将这段代码放到静态方法或单独的类中。


1

对象不是那样工作的,$this始终是同一个对象,并且您在每次迭代中修改它。您可以使用$data[] = clone $this;每次创建一个新实例,但这是糟糕的类设计,最好将类分成两个单独的类。

一个类不应该有多个职责,但是您的类同时充当数据库网关和域模型。


谢谢Fab,我已经解决了将模型和数据库任务分离的问题! - stebcom

0

$this是什么并不清楚,但它显然是某种对象的引用。因此,当你更新那个对象时,数组中保存的所有引用仍然指向同一个对象。所以你必须在每个循环中定义一个新的对象。


0

在迭代开始时,您没有创建新的$this对象。在两次迭代中,您都修改了同一个对象,并将其添加两次到数组中。处理对象时,它们是按引用传递的,这意味着您不会向数组中添加副本,而是添加对$this变量的引用。也许您应该将$row添加到数组中,但仍会覆盖保存在$this中的数据。

您还可以使用clone关键字(请参见手册)保存对象的副本。

更多信息:http://php.net/manual/en/language.references.php


你能帮我一个忙吗?我觉得有人给我们所有人都点了-1。 - yourdeveloperfriend

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