PHP数组的引用与值复制?

时间:2010-08-25 17:11:42

标签: php

我遗漏了一些明显的东西。这是一个微不足道的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

我觉得很清楚: -

任何人都知道我需要做些什么来获取$ 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;
    } 
} 

5 个答案:

答案 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也包含引用。 paramArrayassocArray$row中的所有相应元素实际上都引用了相同的值。因此,当您调用return $this->stmt->fetch()时,它不仅会影响paramArray,而且所有这些引用,一直到$行,因为$rows[]= $row;仍然只复制数组,但不“取消引用”元素。