Edit report at http://bugs.php.net/bug.php?id=51622&edit=1

 ID:                 51622
 Comment by:         urkle at outoforder dot cc
 Reported by:        oliver dot graetz at gmx dot de
 Summary:            ArrayObject::offsetGet should return a reference
 Status:             Open
 Type:               Feature/Change Request
 Package:            SPL related
 PHP Version:        5.2.13
 Block user comment: N
 Private report:     N

 New Comment:

Is this issue fixed in PHP 5.3.4 which supports defining &offsetGet ?
(As documented in http://php.net/manual/en/arrayaccess.offsetget.php )



Actually Just tested and it's not..  Though ArrayAccess by itself works
wonderfully.

--- Test script (Tested on PHP 5.3.5 x86_64 on Fedora 14)

<?php



class Test implements ArrayAccess {

        private $data = array();



        /** Array Access */

        public function offsetExists($offset)

        {

                return isset($this->data[$offset]);

        }



        public function &offsetGet($offset)

        {

                return $this->data[$offset];

        }



        public function offsetSet($offset, $value)

        {

                $this->data[$offset] = $value;

        }



        public function offsetUnset($offset)

        {

                unset($this->data[$offset]);

        }

}



class Test2 extends ArrayObject {

        public function &offsetGet($offset)

        {

                $t =& parent::offsetGet($offset);

                return $t;

        }

}



$t = new Test();

$t['test'] = array(1,2,3,4);

echo serialize($t)."\n";

$t['test'][] = 5;

echo serialize($t)."\n";



$t = new Test2();

$t['test'] = array(1,2,3,4);

echo serialize($t)."\n";

$t['test'][] = 5;

echo serialize($t)."\n";


Previous Comments:
------------------------------------------------------------------------
[2010-08-18 10:21:25] golgote at mamasam dot com

I'd like to see a solution to this problem as well. I have spent
countless hours 

trying to use ArrayObject and ArrayAccess and they both have problems
either 

with get and unset. An unset() on an ArrayObject issues the notice :



        $object["list"][0]["prods"] = "1,3";

        $object["list"][0]["cache"][1] = array(

                        'name' => 'p3',

                        'categories' => array(

                            array('category' => 'c3'), 

                            ),

                        'price' => 3

                        );

        unset($object["list"][0]["cache"][2]);



will issue Notice: Indirect modification of overloaded element... while
this 

works with ArrayAccess! 



But something like a straight :

        $object['arr'][0]['foo'] = 'bar';

will issue the notice with ArrayAccess but not with an ArrayObject!



It's really silly.



I suggest that since this bug hasn't been fixed since 2005, it should be


documented clearly that neither ArrayAccess and ArrayObject work
correctly with 

multidimensional arrays and are just quick, funny but useless hacks so
that 

people stop wasting their time with them.

------------------------------------------------------------------------
[2010-06-03 23:32:03] andrewm dot finewolf at gmail dot com

Arrays in PHP contains references to primitive types and reference
types. Which basically means that if you are post-incrementing an
element, well, it actually works.



Why is ArrayAccess::offsetGet() returns by value instead of by
reference? Wasn't ArrayAccess created to emulate an array? This is a
major inconsistency in the platform and makes this whole interface
pretty useless. This isn't an engine limitation. __get(), __set(),
__isset(), __unset() is returning values by reference without any
problems. Why can't ArrayAccess (when it does pretty much the same
thing?)



Can ArrayAccess::offsetGet() return by reference (or at the very least
create a second interface, "ArrayAccessRef", for this)?

------------------------------------------------------------------------
[2010-04-27 10:02:34] col...@php.net

This is actually a feature request. To be backward compatible, we would
need to 

have a new interface, and obviously a new interface only to solve that
reference 

thing is painful.



The immediate solution is to return an ArrayObject itself, which means
that 

indirect modifications will work.

------------------------------------------------------------------------
[2010-04-21 13:35:50] oliver dot graetz at gmx dot de

Description:
------------
This bug refers to my report filed under
http://bugs.php.net/bug.php?id=34783 which is now more than four years
old. In the meantime I found out that using ArrayObject instead of the
test class the



    $t['huba'][]='three';



actually works, thanks to the SPL using its "implemented in C advantage"
to circumvent the problem. Actually, it works until the programmer
decides to inherit from ArrayObject and overwrite offsetGet(). Then the
problem of the offsetGet() method not returning by reference is back.



Back in 2005 you were very quick to flag the report as BOGUS, but a look
at the source code of "zend_interfaces.c" proves that there is in fact a
problem:



ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offset_get, 0, 0, 1) /*
actually this should be return by ref but atm cannot be */



The best way of dealing with this is not to mark it as BOGUS and deny
that there is a problem. It would be admitting the fault and perhaps
introducing an alternative NewArrayAccess interface that defines
&offsetGet(). So future code can use it without breaking old
implementations.



Test script:
---------------
<?php

class Test1 extends ArrayObject

{

}

class Test2 extends ArrayObject

{

        function offsetGet($key) { return parent::offsetGet($key); }

}



$t1           = new Test1();

$t1['huba']   = array('one','two');

$t1['huba'][] = 'three';

print_r($t1);



$t2           = new Test2();

$t2['huba']   = array('one','two');

$t2['huba'][] = 'three';

print_r($t2);



Expected result:
----------------
Test1 Object

(

    [huba] => Array

        (

            [0] => one

            [1] => two

            [2] => three

        )



)



Test2 Object

(

    [huba] => Array

        (

            [0] => one

            [1] => two

            [2] => three

        )



)

Actual result:
--------------
Test1 Object

(

    [huba] => Array

        (

            [0] => one

            [1] => two

            [2] => three

        )



)



Notice: Indirect modification of overloaded element of Test2 has no
effect in F:\huba.php on line 17

Test2 Object

(

    [huba] => Array

        (

            [0] => one

            [1] => two

        )



)


------------------------------------------------------------------------



-- 
Edit this bug report at http://bugs.php.net/bug.php?id=51622&edit=1

Reply via email to