我遗漏了一些明显的东西。这是一个微不足道的PHP,散落着调试回声:
function echo_rows(&$res) {
$rows= array();
while ($row= $res->fetch()) {
echo $row['ccorID'] . "\r\n";
$rows[]= $row;
echo $rows[0]['ccorID'] . "\r\n";
}
echo "---.---\r\n";
echo count($rows) . "\r\n";
foreach($rows as $row) {
echo $row['ccorID'] . "\r\n";
}
echo json_encode($rows);
}
以下是我在回复中看到的内容:
0
0
3
3
13
13
182
182
---.---
4
182
182
182
182
我觉得很清楚: -
$rows[]= $row;
不执行值复制,尽管它在此处说http://uk.php.net/manual/en/language.types.array.php 任何人都知道我需要做些什么来获取$ row的副本(这是一个关联数组)?
感谢。
编辑:由于你们中的许多人如此坚持要知道$ res是什么,所以这是课程。我真的相信这更容易混淆而不是启发(因此我的OP的遗漏)。class mysqlie_results {
private $stmt;
private $paramArray= array();
private $assocArray= array();
public function __construct(&$stmt) {
$this->stmt= $stmt;
$meta= $stmt->result_metadata();
while ($colData= $meta->fetch_field()) {
$this->paramArray[]= &$this->assocArray[$colData->name];
}
call_user_func_array(array($stmt,'bind_result'),$this->paramArray);
$meta->close();
}
public function __destruct() {
$this->stmt->free_result();
}
public function fetch() {
return $this->stmt->fetch()? $this->assocArray : false;
}
}
答案 0 :(得分:3)
编辑:使用对象只是猜测。事实证明,问题是由其他人之前猜到的引用引起的。
由于我们还不知道$ res是什么以及$res->fetch()
实际返回的内容让我尝试复制行为。
<?php
$res = new Foo;
echo_rows($res);
function echo_rows(&$res) {
// as provided in the question
}
class Foo extends ArrayObject {
protected $bar, $counter;
public function fetch() {
if ( ++$this->counter > 4 ) {
return false;
}
else {
$this->bar['ccorID'] = $this->counter;
return $this->bar;
}
}
public function __construct() {
$this->bar = new ArrayObject;
$this->counter = 0;
}
}
打印
1
1
2
2
3
3
4
4
---.---
4
4
4
4
4
[{"ccorID":4},{"ccorID":4},{"ccorID":4},{"ccorID":4}]
原因是,$ rows中的所有元素都指向同一个底层对象(请参阅http://docs.php.net/language.oop5.references),因为我的类Foo总是返回相同的对象,只是修改了这个单个对象的状态。
更新:“当手册说”使用参考运算符通过引用复制数组时“手册可能意味着什么?”
让我们从这个脚本开始
<?php
$arr = array();
$s = '';
$b = array();
$b['foo'] = $arr;
$b['bar'] = $s;
$b['foo']['bar'] = 1;
$b['bar'] = 'xyz';
var_dump($arr, $s);
输出
array(0) {
}
string(0) ""
即。由于数组包含值的副本,因此$b['foo']['bar'] = 1;
和$b['bar'] = 'xyz';
未更改$ arr和$ s。
现在更改两个作业以使用参考
$b['foo'] = &$arr;
$b['bar'] = &$s;
,输出变为
array(1) {
["bar"]=>
int(1)
}
string(3) "xyz"
即。元素不是副本。
答案 1 :(得分:1)
PHP核心开发人员JohannesSchlüter说Do not use PHP references. PHP中的参考文献大多是PHP 4中的保留。在PHP 5中,在大多数情况下都不需要引用它们。
Returning References上的PHP手册(重点是他们的):
不 使用return-by-reference来提高性能。引擎将自动对其进行自动优化。只有在有正当技术理由的情况下才能返回引用。
如果确实需要克隆数组引用,则可以通过这种方式复制它:
$row = unserialize(serialize($row));
答案 2 :(得分:0)
我敢打赌$res->fetch()
由于某种原因正在返回reference ...尝试这样做以打破参考:
while ($row= $res->fetch()) {
echo $row['ccorID'] . "\r\n";
$rows[]= $row;
echo $rows[0]['ccorID'] . "\r\n";
unset($row);
}
(注意到最后添加的unset
)...
答案 3 :(得分:0)
我会尝试使用array_merge(),但是不清楚这个函数的意图是什么,快速修复只是添加一个索引器,因为你正在做的只是复制引用,而你刚刚更新的每一行都引用了引用到
答案 4 :(得分:0)
让我们仔细看看
while ($colData= $meta->fetch_field()) {
$this->paramArray[]= &$this->assocArray[$colData->name];
}
call_user_func_array(array($stmt,'bind_result'),$this->paramArray);
你有你的参考资料,这会造成麻烦。如果复制包含引用的数组,则结果仍然是包含引用的数组。
尝试
while ($row= $res->fetch()) {
var_dump($row);
你会看到$ row也包含引用。 paramArray
,assocArray
和$row
中的所有相应元素实际上都引用了相同的值。因此,当您调用return $this->stmt->fetch()
时,它不仅会影响paramArray
,而且所有这些引用,一直到$行,因为$rows[]= $row;
仍然只复制数组,但不“取消引用”元素。