Mapping references and values ​​for PHP arrays?

I am missing something obvious. Here's a trivial PHP snippet dotted with debugging echoes:

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); } 

Here is what I see in the answer:

 0 0 3 3 13 13 182 182 ---.--- 4 182 182 182 182 
It seems to me quite clear that: -

Has anyone understood what I need to do to get a copy of the string $ (which is an associative array)?

Thanks.

EDIT: since many of you are so persistent that they know what $ res is, here is a class. I sincerely believe that this will confuse rather than enlighten (hence the omission from my 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; } } 
+4
source share
5 answers

Let's take a closer look

  while ($colData= $meta->fetch_field()) { $this->paramArray[]= &$this->assocArray[$colData->name]; } call_user_func_array(array($stmt,'bind_result'),$this->paramArray); 

There you have your own links and which cause problems. If you copy an array containing the link, the result is an array containing the link.

Try

 while ($row= $res->fetch()) { var_dump($row); 

and you will see that the string $ row also contains links. All of these matching elements in paramArray , assocArray and $row actually refer to the same value. And thus, when you call return $this->stmt->fetch() , it affects not only paramArray , but all of these links, up to $ rows with $rows[]= $row; still copy only the array, but do not "de-reference" the elements.

0
source

edit: Using the object was just a guess. It turns out that the problem is caused by links that were previously suspected.

Since we don’t yet know what $ res is and what $res->fetch() really returns, let me try to reproduce the behavior.

 <?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; } } 

prints

 1 1 2 2 3 3 4 4 ---.--- 4 4 4 4 4 [{"ccorID":4},{"ccorID":4},{"ccorID":4},{"ccorID":4}] 

The reason is that all the elements in $ rows point to the same base object (see http://docs.php.net/language.oop5.references ), since my Foo class always returns the same object and just changes the state of this single object.


update: "what can manual mean when it says:" Use a reference operator to copy an array by reference? "

Let's start with this script.

 <?php $arr = array(); $s = ''; $b = array(); $b['foo'] = $arr; $b['bar'] = $s; $b['foo']['bar'] = 1; $b['bar'] = 'xyz'; var_dump($arr, $s); 

conclusion

 array(0) { } string(0) "" 

i.e. $b['foo']['bar'] = 1; and $b['bar'] = 'xyz'; did not change $ arr and $ s, since the array contains copies of the values.

Now change the two assignments to use links

 $b['foo'] = &$arr; $b['bar'] = &$s; 

and the output changes to

 array(1) { ["bar"]=> int(1) } string(3) "xyz" 

i.e. items are not copies.

+3
source

PHP PHP developer Johannes Schlüter says Don't use PHP links. Links in PHP are mostly a delay since PHP 4. In PHP 5, links are not needed in most cases when you are tempted to use them.

The PHP Handbook for Link Returns says (focus on them):

Use not to increase productivity. The engine automatically optimizes this on its own. Return links only when you have the right technical reason.

If you need to clone an array reference, you can copy it by value as follows:

 $row = unserialize(serialize($row)); 
+1
source

I bet $res->fetch() returns a reference for some reason ... Try this to break the link

 while ($row= $res->fetch()) { echo $row['ccorID'] . "\r\n"; $rows[]= $row; echo $rows[0]['ccorID'] . "\r\n"; unset($row); } 

(Noticed the added unset at the end) ...

0
source

I would try array_merge (), but it is not clear what the intent of this function is. A quick fix simply adds an index, because what you are doing is just copying the link and for every line you just update, where the link to

0
source

All Articles