4

First code and then the question:

class MyArray
{
    private $arrayRef;

    function __construct(&$array){
        $this->arrayRef = $array;
    }

    function addElement($newElement){
        $this->arrayRef[] = $newElement;
    }

    function print(){
        print_r($this->arrayRef);
    }
}

$array = ['first', 'second'];
$arrayObject = new MyArray($array);
$arrayObject->addElement('third');

print_r($array); // prints array containing 2 elements
echo '<br/>';
$arrayObject->print(); // prints array containing 3 elements

Class member $arrayRef, in this example doesn't work as a reference to another array provided in constructor. Argument in constructor is passed by reference, but I guess that doesn't make member $arrayRef also a reference to that array as well.

Why doesn't it work like that and how to make it work?

If you still don't get what I mean: first print_r prints array containing 2 elements, even thought it may be expected to contain 3. When I pass third element to $arrayObject via addElement() I also want it to be added in the $array that I passed to constructor of class.

Scarass
  • 914
  • 1
  • 12
  • 32
  • Yes, your constructor takes a value by reference, but it makes a local copy of it on the line: `$this->arrayRef = $array;`. The rest of the class is working on the instantiated object's copy (`this->arrayRef`), not the original `$array`. Do you want a `global` variable instead? – WillardSolutions Nov 08 '16 at 22:39
  • I want member $arrayRef to be a reference to an array passed in constructor so that any changes made $arrayRef are also made to passed array – Scarass Nov 08 '16 at 22:44

1 Answers1

5

The answer is actually quite simple. Yes, you pass the array by reference via &$array but this reference gets lost when you assign/copy it to the member variable. To keep the reference, you can use the =& operator like so

$this->arrayRef =& $array;

See it work in this fiddle. You can read more about it in this question/answer (just look for reference).

Beware not to use &= (which does a bitwise operation) instead of =& (which assigns by reference).

kero
  • 10,647
  • 5
  • 41
  • 51
  • Okay, I have modified that line the way you suggested, but now I have a problem assigning new values to array, I get error: Cannot use a scalar value as an array. End in debug mode I see taht value of $arrayRef is 0. WTF? $array passed in constructor is initialized. This is now an another question but I would still prefer you'd answer :). If not, still fine. Will check on that error tomorrow. – Scarass Nov 08 '16 at 22:56
  • Oh sorry, I've failed to rewrite your line of code. I've written $this->arrayRef &= $array; LOL – Scarass Nov 08 '16 at 23:12
  • 1
    Yeah this is tricky. As you can see in the last link I posted in the answer, `&=` does a bitwise operation while `=&` assigns by reference. To be honest, working with references like this is quite uncommon in PHP, so I had to look it up myself (you usually just return the new array and go on from there). I've added this pitfall. If this answered your question, please consider marking it as accepted – kero Nov 08 '16 at 23:38
  • I need this for a specific purpose. Could you still just explain why is copying the whole array more standard/better than just providing a reference to it? If deep copy isn't necessary? I really don't get it. Isn't it slower? – Scarass Nov 09 '16 at 00:29
  • 1
    I think standard is the word here rather than better. Of course, this is just my personal opinion, but as I said working with copies rather than references is more common in PHP. Other than that, sadly, I have no answer. You are welcome to dig through large/commonly used frameworks. Or look at the internal functions themselves. You rarely see references (and when you do, it is with very old functions), but rather returning a modified copy. All of the array functions (`array_unique`, `_merge`, etc) do it like this i.e. – kero Nov 09 '16 at 00:32
  • Not a PHP expert here, but according to the documentation you shouldn't use references purely for performance reasons, but only if needed by the logic of your code. The idea here is that PHP automatically uses references when it thinks it's faster that way. Fiddling with reference when it's not strictly needed can be cumbersome and complicated for beginners. However coming from the C/C++ side I personally don't care about these things. And I generally don't trust automatic optimizations. So I think it's purely personal preference. – Scindix Apr 29 '19 at 08:17