Edit report at https://bugs.php.net/bug.php?id=55406&edit=1
ID: 55406 Updated by: le...@php.net Reported by: chrisstocktonaz at gmail dot com Summary: get_object_vars and array casting when extending ArrayObject -Status: Open +Status: Not a bug Type: Bug Package: SPL related Operating System: Linux PHP Version: 5.4.0alpha3 Block user comment: N Private report: N New Comment: This is the expected behavior (I think). ArrayObject is complex and doesn't work as most people would expect. It's hard for me to keep straight sometimes. You need to set the STD_PROP_LIST bit for this to behave the way you are expecting. Previous Comments: ------------------------------------------------------------------------ [2011-08-12 11:09:39] RQuadling at GMail dot com Adding ... public function __construct (array $input = array(), $flags = ArrayObject::STD_PROP_LIST, $iterator_class = 'ArrayIterator') { parent::__construct($input, $flags, $iterator_class); } as the constructor for TestTwo will output ... array(1) { ["TestOne_1"]=> int(1) } array(1) { ["TestOne_1"]=> int(1) } array(1) { ["TestTwo_1"]=> int(1) } array(1) { ["TestTwo_1"]=> int(1) } array(2) { ["TestThree_1"]=> int(1) ["TestTwo_1"]=> int(1) } array(2) { ["TestThree_1"]=> int(1) ["TestTwo_1"]=> int(1) } So, is this a bug? Dox says ... "ArrayObject::STD_PROP_LIST Properties of the object have their normal functionality when accessed as list (var_dump, foreach, etc.)." So, without this flag (a bitmask) being set, the "properties" aren't accessible in the way you think they should be. ------------------------------------------------------------------------ [2011-08-11 20:41:44] chrisstocktonaz at gmail dot com My expected result had a typo, "TestOne_1" would not exist in testtwo or testthree classes. Here is a patch for this: --- ext/spl/spl_array.c 2011-07-25 04:35:02.000000000 -0700 +++ ext/spl/spl_array.c 2011-08-11 13:38:52.000000000 -0700 @@ -746,7 +746,12 @@ { spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC); - return spl_array_get_hash_table(intern, 1 TSRMLS_CC); + HashTable *hh = zend_std_get_properties(object TSRMLS_CC); + HashTable *ht = spl_array_get_hash_table(intern, 1 TSRMLS_CC); + + zend_hash_merge(hh, ht, NULL, NULL, sizeof(zend_class_entry *), 0); + + return hh; } /* }}} */ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ ------------------------------------------------------------------------ [2011-08-11 19:59:18] chrisstocktonaz at gmail dot com Description: ------------ As discussed on internals mailing list here [1], ArrayObject I think is overriding the get_properties handler in a bit to simple of a way. I think the ArrayObject should merge the spl hash with the default handler. [1] http://news.php.net/php.internals/54508 Test script: --------------- --Code class TestOne { public $TestOne_1 = 1; } class TestTwo extends ArrayObject { public $TestTwo_1 = 1; } class TestThree extends TestTwo { public $TestThree_1 = 1; } $t1 = new TestOne; var_dump((array) $t1, get_object_vars($t1)); $t2 = new TestTwo; var_dump((array) $t2, get_object_vars($t2)); $t3 = new TestThree; var_dump((array) $t3, get_object_vars($t3)); Expected result: ---------------- array(1) { ["TestOne_1"]=> int(1) } array(1) { ["TestOne_1"]=> int(1) } array(0) { // TestOne_1 // TestTwo_1 } array(0) { // TestOne_1 // TestTwo_1 } array(0) { // TestOne_1 // TestTwo_1 // TestThree_1 } array(0) { // TestOne_1 // TestTwo_1 // TestThree_1 } Actual result: -------------- array(1) { ["TestOne_1"]=> int(1) } array(1) { ["TestOne_1"]=> int(1) } array(0) { } array(0) { } array(0) { } array(0) { } ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=55406&edit=1