NotionCommotion Posted March 9, 2017 Share Posted March 9, 2017 How do I set the value of an element in an array stored in SplObjectStorage? As seen, I receive a Indirect modification of overloaded element of SplObjectStorage has no effect warning. Thanks <?php $s = new SplObjectStorage(); $o1 = new StdClass; $s->attach($o1,123); echo('$s[$o1]='); var_dump($s[$o1]); echo('$s[$o1]=321;'."\n"); $s[$o1]=321; echo('$s[$o1]='); var_dump($s[$o1]); $o2 = new StdClass; $s->attach($o2,['a'=>111,'b'=>222]); echo('$s[$o2]='); var_dump($s[$o2]); echo('s[$o2][a]='); var_dump($s[$o2]['a']); echo('$s[$o2][a]=333;'."\n"); $s[$o2]['a']=333; var_dump($s[$o2]['a']); $s[$o1]=int(123) $s[$o1]=321; $s[$o1]=int(321) $s[$o2]=array(2) { ["a"]=> int(111) ["b"]=> int(222) } s[$o2][a]=int(111) $s[$o2][a]=333; <br /> <b>Notice</b>: Indirect modification of overloaded element of SplObjectStorage has no effect in <b>/var/www/public/spl.php</b> on line <b>27</b><br /> int(111) Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted March 9, 2017 Author Share Posted March 9, 2017 Really? The only way? Why? <?php $s = new SplObjectStorage(); $o = new StdClass; $s->attach($o,['a'=>111,'b'=>222]); $bla=$s[$o]; $bla['b']=555; $s[$o]=$bla; Quote Link to comment Share on other sites More sharing options...
requinix Posted March 9, 2017 Share Posted March 9, 2017 Arrays are by-val so yes: you'd have to get, update, and set separately. Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted March 9, 2017 Author Share Posted March 9, 2017 Arrays are by-val so yes: you'd have to get, update, and set separately. How does that relate to the warning Indirect modification of overloaded element of SplObjectStorage has no effect warning? When storing an array, is it caused by PHP internally hashing the array and turning it into a string and storing that hash? Where is this documented? Is it more typical to use an object since they are passed by reference? $s->attach($o,(object)['a'=>111,'b'=>222]); $s[$o1]->b=555; Quote Link to comment Share on other sites More sharing options...
kicken Posted March 9, 2017 Share Posted March 9, 2017 The warning is because indexing an object like an array is just a shorthand for calling the offsetGet method of the ArrayAccess interface. That method returns the data stored under the given index by value so changes made to it will not persist. To have the change persist you have to re-assign the index the new changed value so that the offsetSet method is called. You can see this warning if you create your own object that implements ArrayAccess and try to do the same: <?php class MyStorage implements ArrayAccess { private $map; public function offsetExists($n){ return isset($this->map[$n]); } public function offsetGet($n){ return $this->map[$n]; } public function offsetSet($n, $v){ $this->map[$n] = $v; } public function offsetUnset($n){ unset($this->map[$n]); } } $s = new MyStorage(); $s['blah'] = ['a' => 1, 'b' => 2, 'c' => 3]; var_dump($s['blah']); $s['blah']['a'] = 10; var_dump($s['blah']); Quote Link to comment Share on other sites More sharing options...
requinix Posted March 9, 2017 Share Posted March 9, 2017 Is it more typical to use an object since they are passed by reference?I would expect that it's typical to put objects into SplObjectStorage. With what you're doing now you're basically treating the class as a fancy type of array that allows using objects as keys. Quote Link to comment Share on other sites More sharing options...
NotionCommotion Posted March 9, 2017 Author Share Posted March 9, 2017 I would expect that it's typical to put objects into SplObjectStorage. With what you're doing now you're basically treating the class as a fancy type of array that allows using objects as keys. Agree, I am hacking an array to mimic an object. There just easier to initiate for the type I needed. Better off using an object, and it works as well. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.