PHP link causes data corruption

I am writing PHP code to do some conversion of each value in an array and then add some values ​​to the array from an external source (MySQL cursor or, say, another array). If I use foreach and a link to convert array values

 <?php $data = array('a','b','c'); foreach( $data as &$x ) $x = strtoupper($x); $extradata = array('d','e','f'); // actually it was MySQL cursor while( list($i,$x) = each($extradata) ) { $data[] = strtoupper($x); } print_r($data); ?> 

( Here it is in PHPfiddle )

what data is damaged. Therefore i get

 Array ( [0]=>A [1]=>B [2]=> [3]=>D [4]=>E [5] =>F ) 

instead

 Array ( [0]=>A [1]=>B [2]=>C [3]=>D [4]=>E [5] =>F ) 

When I do not use the link and write

 foreach( $data as &$x ) $x = strtoupper($x); 

the conversion does not occur, of course, but the data is also not corrupted, so I get

 Array ( [0]=>A [1]=>B [2]=>C [3]=>D [4]=>E [5] =>F ) 

If I write code like this

 <?php $result = array(); $data1 = array('a','b','c'); foreach( $data1 as $x ) $result[] = strtoupper($x); $data2 = array('d','e','f'); // actually it was MySQL cursor while( list($i,$x) = each($data2) ) { $result[] = strtoupper($x); } print_r($result); ?> 

everything works as expected.

 Array ( [0]=>A [1]=>B [2]=>C [3]=>D [4]=>E [5] =>F ) 

Of course, copying data solves the problem. But I would like to understand that there is a strange problem with this link and how to avoid such problems. Maybe it's generally bad to use PHP links in your code (for example, many talk about C pointers)?

+6
source share
3 answers

The mechanism of references to the PHP language has a specific feature that is not common to other programming languages. It is generally accepted that an object reflects all changes made to its properties through any reference to it. But the assignment of the link itself is either prohibited or makes a reference point for another object. Instead, link assignment in PHP replaces the entire base object (the object indicated by the link) with the one assigned. So

 $a = 1; $b = 2; $r = &$a; $r = $b; echo $a; // will output '2' 

This is true for assignment, but not for calling unset , which will not destroy the underlying object, but breaks the connection between the referenced and pointed objects.

 $a = 1; $b = 2; $r = &$a; unset($r); //! $r = $b; echo $a; // will output '1' 

In some cases, this reference behavior is useful, but it is often misunderstood, which leads to problems, as shown in the figure.

For aviod problems with PHP links, you should:

  • Install each link as early as possible (at the moment when it becomes unnecessary).

So this code will work

 <?php $data = array('a','b','c'); foreach( $data as &$x ) $x = strtoupper($x); unset($x); $extradata = array('d','e','f'); // actually it was MySQL cursor while( list($i,$x) = each($extradata) ) { $data[] = strtoupper($x); } print_r($data); ?> 
  • This is generally a bad style for reusing local variable names in multiple control structures.

So the following code will work too

 <?php $data = array('a','b','c'); foreach( $data as &$x ) $x = strtoupper($x); $extradata = array('d','e','f'); // actually it was MySQL cursor while( list($i,$y) = each($extradata) ) { $data[] = strtoupper($y); } 
+15
source

This works for me .... Maybe I could do it differently if I knew what you were trying to do ... but it should work.

 $data = array('a','b','c'); foreach( $data as &$x ) $x = strtoupper($x); $extradata = array('d','e','f'); // actually it was MySQL cursor foreach ($extradata as &$x) { $data[] = strtoupper ($x); } 
0
source

You are again using $x in a loop over $extradata , which makes the links uncomfortable.

It works:

 $data = array('a','b','c'); foreach( $data as &$x ) $x = strtoupper($x); $extradata = array('d','e','f'); // actually it was MySQL cursor while( list($i,$anything_but_x) = each($extradata) ) { $data[] = strtoupper($anything_but_x); } print_r($data); 

  • Do not reuse variables
  • Avoid links
0
source

Source: https://habr.com/ru/post/956731/


All Articles