Error "Attempting to change a non-object property"

Can someone tell me why the following code will have different results?

unset object property

$s = new StdClass; unset($s->a->b); //it is working fine unset($s->x->y->z); //it is got an error: Attempt to modify property of non-object 

disable array index

 $a = array(); unset($a[1][2]); //it is working fine unset($a[3][4][5]); //it is working fine 
+8
php
source share
1 answer

StdClass vs Array

Array

Arrays in PHP allow the implicit creation of multidimensional arrays from the database. i.e:

 $a[] = "something"; //new array created, indexed at 0 $a[] = "yep"; //adds element to end of array (array_push); 

var_dump from the above gives:

 array(2) { [0]=> string(9) "something" [1]=> string(3) "yep" } 

PHP 5.4.x does not specify any notifications. You can also do:

 $a[] = "something"; $a[1][2][3] = "yep"; 

And all levels of the array are implicitly created, giving var_dump of:

 array(2) { [0]=> string(9) "something" [1]=> array(1) { [2]=> array(1) { [3]=> string(3) "yep" } } } 

PHP was designed to handle this type of array with ease. For more information on how arrays are processed, read Array Type . Because of this, if you access a key inside an array to assign values, if it does not already exist, it is implicitly created. When used in combination with unset , no errors occur because it can check the final array and see that its key does not exist.

Stdclass

Since this is an object , properties must be explicitly created for what was added to it. For example:

 $s = new StdClass; $s->a = new stdClass; $s->a->b = new stdClass; $s->a->b->c = "test"; 

Will yield:

 object(stdClass)#1 (1) { ["a"]=> object(stdClass)#2 (1) { ["b"]=> object(stdClass)#3 (1) { ["c"]=> string(4) "test" } } } 

As you create the object needed to reach this point. If, however, you try to use:

 $s = new StdClass; $s->a->b->c = "test"; 

You will receive an error message:

Warning: creating a default object from an empty value in a .php file on line x

However, then an object is created that gives var_dump of:

 object(stdClass)#1 (1) { ["a"]=> object(stdClass)#2 (1) { ["b"]=> object(stdClass)#3 (1) { ["c"]=> string(4) "test" } } } 

This is what you would expect it to go through the values ​​of a and create the default object, then b , and then set the object property b->c to "test". When you go to unset values ​​in an object, it will not go through all the properties for the default objects for you. For example,

 $s = new StdClass; unset($s->a->b); 

It will not give you an error, because a may be a property of $s , and will execute the default type for the object, and then disable b . However, he will not go further on the list.

 unset($s->a->b->c); 

It goes with the assumption that b is the created object inside a , but it is not, so you are trying to access the property of a non-object using b->c . A more explicit example:

 $s = new stdclass; $s->a->b->c = array(); unset($s->a->b->c->d); 

unset no errors will be thrown here, because it will introduce type c for the object, and then unset d . You get a warning that it still reaches c as stdClass . This shows that the last element / class will be an application-type object to access the property if it is not already one, but it will not enter all the elements to access the last property when using unset .

Conclusion

In general, the difference between how PHP processes arrays and how it processes objects. Objects have a stricter standard and are not meant to cast types to multiple levels, because they are accessed as unset , while arrays. With objects, you can implicitly create them at the required levels (getting a warning how you do it), but when you turn off type-casting does not happen, and you get access to properties that do not exist.

+18
source share

All Articles