Skip to content

Commit b0c7ea4

Browse files
committed
Change the order of properties used in foreach(), var_dump(), serialize(), comparison, etc. Now properties are ordered according to their layout in zend_object structure.
2 parents 47a2e5c + c9a9362 commit b0c7ea4

36 files changed

+283
-286
lines changed

UPGRADING

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ PHP 8.1 UPGRADE NOTES
211211
5. Changed Functions
212212
========================================
213213

214+
- Core:
215+
. Properties order used in foreach, var_dump(), serialize(), object comparison
216+
etc. was changed. Now properties are naturally ordered according to their
217+
declaration and inheritance. Prpoerties declared in a base class are going
218+
to be before the child properties. This order is consistent with internal
219+
layout of properies in zend_objct structure and repeats the order in
220+
default_properties_table[] and properties_info_table[]. The old order was
221+
not documented and was caused by class inheritance implementation details.
222+
214223
- Filter:
215224
. The FILTER_FLAG_ALLOW_OCTAL flag of the FILTER_VALIDATE_INT filter now accept
216225
octal string with the leading octal prefix ("0o"/"0O")

Zend/tests/bug27798.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ array(3) {
5757
}
5858
Child::__construct
5959
array(3) {
60-
["Baz"]=>
61-
int(4)
6260
["Foo"]=>
6361
int(1)
6462
["Bar"]=>
6563
int(2)
64+
["Baz"]=>
65+
int(4)
6666
}
6767
array(1) {
6868
["Foo"]=>

Zend/tests/bug60536_003.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ var_dump($b);
3232
?>
3333
--EXPECTF--
3434
object(SubclassA)#%d (2) {
35-
["hello":"SubclassA":private]=>
36-
int(0)
3735
["hello":"BaseWithPropA":private]=>
3836
int(0)
37+
["hello":"SubclassA":private]=>
38+
int(0)
3939
}
4040
object(SubclassB)#%d (2) {
41-
["hello":"SubclassB":private]=>
42-
int(0)
4341
["hello":"BaseWithTPropB":private]=>
4442
int(0)
43+
["hello":"SubclassB":private]=>
44+
int(0)
4545
}

Zend/tests/bug79862.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ NULL
4545
NULL
4646
NULL
4747
object(c)#1 (6) {
48-
["prop1"]=>
49-
int(1)
50-
["prop2":protected]=>
51-
int(2)
5248
["prop3":"a":private]=>
5349
int(3)
5450
["prop4":"a":private]=>
5551
int(4)
52+
["prop1"]=>
53+
int(1)
54+
["prop2":protected]=>
55+
int(2)
5656
["prop5"]=>
5757
int(5)
5858
["prop6"]=>

Zend/tests/get_mangled_object_vars.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ echo "\n";
3333
?>
3434
--EXPECT--
3535
array (
36-
'' . "\0" . 'B' . "\0" . 'priv' => 4,
3736
'pub' => 1,
3837
'' . "\0" . '*' . "\0" . 'prot' => 2,
3938
'' . "\0" . 'A' . "\0" . 'priv' => 3,
39+
'' . "\0" . 'B' . "\0" . 'priv' => 4,
4040
'dyn' => 5,
4141
6 => 6,
4242
)

Zend/tests/objects_033.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ print_r($a, true);
2424
var_dump($a < $b);
2525
?>
2626
--EXPECT--
27-
bool(false)
28-
bool(false)
27+
bool(true)
28+
bool(true)

Zend/tests/traits/property008.phpt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,20 @@ var_dump($b);
4242
?>
4343
--EXPECT--
4444
object(SubclassClassicInheritance)#1 (2) {
45-
["hello":"SubclassClassicInheritance":private]=>
46-
int(0)
4745
["hello":"BaseWithPropA":private]=>
4846
int(0)
47+
["hello":"SubclassClassicInheritance":private]=>
48+
int(0)
4949
}
5050
object(SubclassA)#2 (2) {
51-
["hello":"SubclassA":private]=>
52-
int(0)
5351
["hello":"BaseWithPropA":private]=>
5452
int(0)
53+
["hello":"SubclassA":private]=>
54+
int(0)
5555
}
5656
object(SubclassB)#3 (2) {
57-
["hello":"SubclassB":private]=>
58-
int(0)
5957
["hello":"BaseWithTPropB":private]=>
6058
int(0)
59+
["hello":"SubclassB":private]=>
60+
int(0)
6161
}

Zend/zend_object_handlers.c

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,41 +63,24 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
6363
if (!zobj->properties) {
6464
zend_property_info *prop_info;
6565
zend_class_entry *ce = zobj->ce;
66-
uint32_t flags = 0;
66+
int i;
6767

6868
zobj->properties = zend_new_array(ce->default_properties_count);
6969
if (ce->default_properties_count) {
7070
zend_hash_real_init_mixed(zobj->properties);
71-
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
72-
if (!(prop_info->flags & ZEND_ACC_STATIC)) {
73-
flags |= prop_info->flags;
71+
for (i = 0; i < ce->default_properties_count; i++) {
72+
prop_info = ce->properties_info_table[i];
7473

75-
if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
76-
HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
77-
}
78-
79-
_zend_hash_append_ind(zobj->properties, prop_info->name,
80-
OBJ_PROP(zobj, prop_info->offset));
74+
if (!prop_info) {
75+
continue;
8176
}
82-
} ZEND_HASH_FOREACH_END();
83-
if (flags & ZEND_ACC_CHANGED) {
84-
while (ce->parent && ce->parent->default_properties_count) {
85-
ce = ce->parent;
86-
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
87-
if (prop_info->ce == ce &&
88-
!(prop_info->flags & ZEND_ACC_STATIC) &&
89-
(prop_info->flags & ZEND_ACC_PRIVATE)) {
90-
zval zv;
91-
92-
if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
93-
HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
94-
}
95-
96-
ZVAL_INDIRECT(&zv, OBJ_PROP(zobj, prop_info->offset));
97-
zend_hash_add(zobj->properties, prop_info->name, &zv);
98-
}
99-
} ZEND_HASH_FOREACH_END();
77+
78+
if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) {
79+
HT_FLAGS(zobj->properties) |= HASH_FLAG_HAS_EMPTY_IND;
10080
}
81+
82+
_zend_hash_append_ind(zobj->properties, prop_info->name,
83+
OBJ_PROP(zobj, prop_info->offset));
10184
}
10285
}
10386
}
@@ -1555,6 +1538,7 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
15551538
}
15561539
if (!zobj1->properties && !zobj2->properties) {
15571540
zend_property_info *info;
1541+
int i;
15581542

15591543
if (!zobj1->ce->default_properties_count) {
15601544
return 0;
@@ -1570,14 +1554,18 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
15701554
}
15711555
Z_PROTECT_RECURSION_P(o1);
15721556

1573-
ZEND_HASH_FOREACH_PTR(&zobj1->ce->properties_info, info) {
1574-
zval *p1 = OBJ_PROP(zobj1, info->offset);
1575-
zval *p2 = OBJ_PROP(zobj2, info->offset);
1557+
for (i = 0; i < zobj1->ce->default_properties_count; i++) {
1558+
zval *p1, *p2;
1559+
1560+
info = zobj1->ce->properties_info_table[i];
15761561

1577-
if (info->flags & ZEND_ACC_STATIC) {
1562+
if (!info) {
15781563
continue;
15791564
}
15801565

1566+
p1 = OBJ_PROP(zobj1, info->offset);
1567+
p2 = OBJ_PROP(zobj2, info->offset);
1568+
15811569
if (Z_TYPE_P(p1) != IS_UNDEF) {
15821570
if (Z_TYPE_P(p2) != IS_UNDEF) {
15831571
int ret;
@@ -1597,7 +1585,7 @@ ZEND_API int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
15971585
return 1;
15981586
}
15991587
}
1600-
} ZEND_HASH_FOREACH_END();
1588+
}
16011589

16021590
Z_UNPROTECT_RECURSION_P(o1);
16031591
return 0;

ext/date/tests/DateTimeZone_clone_basic2.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,28 +51,28 @@ object(DateTimeZoneExt1)#%d (4) {
5151
string(13) "Europe/London"
5252
}
5353
object(DateTimeZoneExt2)#%d (6) {
54-
["property3"]=>
55-
bool(true)
56-
["property4"]=>
57-
float(10.5)
5854
["property1"]=>
5955
int(99)
6056
["property2"]=>
6157
string(5) "Hello"
58+
["property3"]=>
59+
bool(true)
60+
["property4"]=>
61+
float(10.5)
6262
["timezone_type"]=>
6363
int(3)
6464
["timezone"]=>
6565
string(13) "Europe/London"
6666
}
6767
object(DateTimeZoneExt2)#%d (6) {
68-
["property3"]=>
69-
bool(true)
70-
["property4"]=>
71-
float(10.5)
7268
["property1"]=>
7369
int(99)
7470
["property2"]=>
7571
string(5) "Hello"
72+
["property3"]=>
73+
bool(true)
74+
["property4"]=>
75+
float(10.5)
7676
["timezone_type"]=>
7777
int(3)
7878
["timezone"]=>

ext/date/tests/DateTime_clone_basic2.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ object(DateTimeExt1)#%d (5) {
5555
string(3) "GMT"
5656
}
5757
object(DateTimeExt2)#%d (7) {
58-
["property3"]=>
59-
bool(true)
60-
["property4"]=>
61-
float(10.5)
6258
["property1"]=>
6359
int(99)
6460
["property2"]=>
6561
string(5) "Hello"
62+
["property3"]=>
63+
bool(true)
64+
["property4"]=>
65+
float(10.5)
6666
["date"]=>
6767
string(26) "2009-02-03 12:34:41.000000"
6868
["timezone_type"]=>
@@ -71,14 +71,14 @@ object(DateTimeExt2)#%d (7) {
7171
string(3) "GMT"
7272
}
7373
object(DateTimeExt2)#%d (7) {
74-
["property3"]=>
75-
bool(true)
76-
["property4"]=>
77-
float(10.5)
7874
["property1"]=>
7975
int(99)
8076
["property2"]=>
8177
string(5) "Hello"
78+
["property3"]=>
79+
bool(true)
80+
["property4"]=>
81+
float(10.5)
8282
["date"]=>
8383
string(26) "2009-02-03 12:34:41.000000"
8484
["timezone_type"]=>

0 commit comments

Comments
 (0)