Why/how does joining arrays with + in PHP work? - php

I've noticed recently in PHP you can do this.
$myNewArray = $oldArray + $someArray;
This looks completely different to anything I've seen before involving manipulating arrays in PHP.
How and why does it work? Are there any pitfalls?
I have recently started using it in some places where I may have used array_unshift() and array_merge().

When in doubt, consult the documentation. The behavior is different from array_merge: array_merge appends/overwrites, + only appends.
Example:
<?php
$a = Array('foo'=>'bar','baz'=>'quux');
$b = Array('foo'=>'something else','xyzzy'=>'aaaa');
$c = $a + $b;
$d = array_merge($a,$b);
print_r($c);
print_r($d);
Output - as you see, array_merge overwrote the value from $a['foo'] with $b['foo']; $a+$b did not:
Array
(
[foo] => bar
[baz] => quux
[xyzzy] => aaaa
)
Array
(
[foo] => something else
[baz] => quux
[xyzzy] => aaaa
)

An operation is defined in the compiler for + when both operands are arrays. It does the intuitive operation of joining them.

One of the pitfalls is what happens when one of the variables is not an array.
array_merge:
Warning: array_merge(): Argument #2 is not an array in ...
+-operator:
Fatal error: Unsupported operand types in ...

Related

PHP how come one element of the array is by reference and the other by value when passing a two element array as a by value parameter?

Can someone explain this strange behaviour I am witnessing in PHP 8.1.6?
I guess the behaviour is according to standards, I just don't understand it. The function call has a parameter by value, yet the array is changed after the call, all because of the reference to the first element.
$arr = [3, 4];
$ref = &$arr[0] ; // this statement causes the weird behaviour. Without it all is ok
print_r($arr); // as expected
print_r(doSomethingTo($arr)); // as expected
print_r($arr); // WHAT JUST HAPPENED?
function doSomethingTo($arr) {
// $arr BY VALUE
foreach($arr as $k => $v)
$arr[$k]=$v+1 ;
return $arr ;
}
result:
Array
(
[0] => 3
[1] => 4
)
Array
(
[0] => 4
[1] => 5
)
Array
(
[0] => 4
[1] => 4
)
Why? Why does the reference to the first array element change the behaviour of the by value parameter passing? The first element was now passed by reference to the function, and the second by value! ???
Thank you for an explanation!
A little complex formulated answer I found at https://www.php.net/manual/en/language.references.whatdo.php
I will translate the answer to this particular situation.
The thing many people may not realise, is, is that $a =& $b does not mean that $a references now to $b, but $a and $b BOTH become references to the same value that was originally contained in $b.
So when evaluating $ref = &$arr[0] ; the $arr[0] element and the $ref become both references to the 3 value.
Now when an array is passed as a parameter by value, the array is always duplicated. Same happens here.
Which means the $arr[0] reference is duplicated too, i.e. in the duplicate array another reference is created to the same 3 value. So we have $ref, the original $arr[0] and the $arr[0] within the function all being references to the 3 value.
When either of these three references gets an assignment, of course the value changes.
Thank you #Sammitch for setting me on the right track!!!

Confusing Result with array_shift

I'm facing some strange behavior with the array_shift function in PHP:
function shift($arr)
{
array_shift($arr);
}
$a = [1, 2, 3];
shift($a);
print_r($a);
Output:
Array ( [0] => 1 [1] => 2 [2] => 3 )
My Expected Output:
Array ( [0] => 2 [1] => 3 )
Explanation:
I believe that $a and $arr, despite being different references, point to the same array object. I expect array_shift to look where $arr is pointing and modify (shorten) that array. Then that change will be visible when looking up the array via $a.
However, when I test my theory, no change is visible. The array is just as long as before array_shift was called. What gives?
The $arr inside your function is not the same array as $a. A local copy is created unless you pass it by reference, e.g.
function shift(&$arr) ...
Check the PHP documentation on variable scope:
However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope.
array_shift is working the way you expect it to, though. You can add a print_r($arr); inside your function after you do the array_shift to see the shortened version of the array within the function scope. It just won't affect the original array unless you pass it by reference.

How To Keep Original Key on Array Merge

I have two dynamic associated array and I am trying to merge them into one array BUT I need to keep the original keys as the orginal arrays but in return I am getting [0] for A which I need to keep it [1] as it was in array $a
$a = ["1"=>"A", "2"=>"B", "3"=>"C"];
$b = ["n"=>"5"];
$c = array_merge($a,$b);
print_r($c);
Array (
[0] => A
[1] => B
[2] => C
[n] => 5 )
In order to preserve keys of your array you need to use + operator over here like as
$a = ["1"=>"A", "2"=>"B", "3"=>"C"];
$b = ["n"=>"5"];
$c = $a + $b;
print_r($c);
You can check PHP Manuals Example #2 Simple array_merge() example
i am not a php developer. so there could be better answers out there
the php documentation says that numerical keys are new numbered. i think that even a string as key with a nummeric value is interpretet as number.
can you try this (not the added 'a' on the nummeric keys):
$a = ["1a"=>"A", "2a"=>"B", "3a"=>"C"];
$b = ["n"=>"5"];
$c = array_merge($a,$b);
print_r($c);
it is not clean code, but after this you can "remove" the 'a' and you have your numeric key

Misunderstanding the behavior of array_udiff

I am having troubles to understand how array_udiff works.
According to the documentation:
array_udiff ($array1, $array2, data_compare_func)
[...] data_compare_func function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
So considering this function:
function please_compare($a, $b) {
return $a !== $b;
};
if $a equals $b, the method will return 0, 1 otherwise (because of this).
(There is no -1 returned here and I have the feeling that the explanation comes from there but I can just compare that the values are different, not that one is greater than the other one.)
Could someone explain me array_udiff's behavior in the following snippet? I also included the output of array_diff, which is actually the behavior I was expecting?
$array1 = array('a', 'b', 'c', 'd');
$array2 = array('a', 'b', 'c');
print_r(array_udiff($array1, $array2, 'please_compare'));
/* Returns:
Array
(
[0] => a
[1] => b
[3] => d
)
*/
print_r(array_diff($array1, $array2));
/* Returns:
Array
(
[3] => d
)
*/
array_udiff relies on the comparison function returning appropriate values, because it ranks the elements of your arrays. If you add some output to your comparison function, you will see that array_udiff first determines the sort order for both arrays, and only after it has done this does it start comparing array1 elements to array2 elements. By returning 1 from your comparison function, you are telling array_udiff that 'a' > 'b' and 'b' > 'a', and similarly for all other elements in both arrays. In your particular case, this causes array_udiff to think that everything in array1 > everything in array2, until it finally happens to compare the 'c' in array1 to the 'c' in array2, and gets 0 back from your function (this is why it left 'c' out of the result). See this PHP fiddle for a demonstration of the internal working of array_udiff.

Removing duplicates with array_unique giving wrong result

i have two array and i want to make unique array with single array
for example i have $a=array(3); and $b=array(1,2,3) so i want $c=array(1,2,3)
i made a code like:
$a=array(3);
$b=explode(',','1,2,3');
$ab=$a+$b;
$c=array_unique ($ab);
print_r($c);
it gives me Array ( [0] => 3 [1] => 2 )
but i want to Array ( [0] => 1 [1] => 2 [2] => 3 )
$a = array(1,2,3,4,5,6);
$b = array(6,7,8,2,3);
$c = array_merge($a, $b);
$c = array_unique($c);
The operation
$ab = $a + $b
Is giving you a result you did not expect. The reason for this behaviour has been explained previously at PHP: Adding arrays together
$ab is Array ( [0] => 3 [1] => 2 [2] => 3 )
The + operator appends elements of remaining keys from the right
handed array to the left handed, whereas duplicated keys are NOT
overwritten.
array_merge provides a more intuitive behaviour.
Array merge, man. Array merge.
Anyway, as this answer for similar question ( https://stackoverflow.com/a/2811849/223668 ) tells us:
The + operator appends elements of remaining keys from the right handed array to the left handed, whereas duplicated keys are NOT overwritten.
If you have numeric keys (as in standard tables), they are for for sure duplicate in both arrays and the result is far from desired.
So the code should look like that:
$c = array_unique(array_merge($a, $b));
You need to use this array_merge to concat two array.
http://www.php.net/manual/en/function.array-merge.php
not
$ab = $a + $b

Categories