⬆️ ⬇️

How to access all properties of an object without using "reflection"

Why get access to all the properties of the object and not to change its interface? For example, in order to write your own serialization . Or to send an object in an acceptable form using http. Or for something else.



Take for experiment a simple class.



class aClass { protected $protected_property = 'protected_value'; private $private_property = 'private_value'; public $public_property = 'public_value'; } $an_object = new aClass; var_dump($an_object); // object(aClass)#1 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // } 




If you use the "reflection", then you can get all the properties of the object, for example, in this way.

')

 $an_array = array(); $reflection = new ReflectionClass($an_object); $properties = $reflection->getProperties(); foreach ($properties as $property) { $property->setAccessible(true); $an_array[$property->getName()] = $property->getValue($an_object); if (!$property->isPublic()) $property->setAccessible(false); } var_dump($an_array); // array(3) { // ["protected_property"]=> // string(15) "protected_value" // ["private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // } 




There is an easier way to get all the properties as an array.



 $an_array = (array) $an_object; var_dump($an_array); // array(3) { // [" * protected_property"]=> // string(15) "protected_value" // [" aClass private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // } 




It turned out a bit "dirty", if necessary, you can clear the keys from unnecessary data. For example, like this:



 $key = ($key{0} === "\0") ? substr($key, strpos($key, "\0", 1) + 1) : $key; 




By the way, the reverse trick with converting an array into an object will not work. Thus, you can get only the object stdClass.



 $an_another_object = (object) $an_array; var_dump($an_another_object); // object(stdClass)#6 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // } 




There is still an undocumented way to get properties. This method even looks like a bug , but it is not so, so it can be safely used.



 $an_array = array(); reset($an_object); while (list($key, $val) = each($an_object)) $an_array[$key] = $val; var_dump($an_array); // array(3) { // [" * protected_property"]=> // string(15) "protected_value" // [" aClass private_property"]=> // string(13) "private_value" // ["public_property"]=> // string(12) "public_value" // } 




In turn, to set a new value for an arbitrary property (including a private one), you can use another undocumented method .



 $an_array["\0aClass\0private_property"] = 'new_private_value'; array_walk($an_object, function(&$val, $key, $array){$val = $array[$key];}, $an_array); var_dump($an_object); // object(aClass)#1 (3) { // ["protected_property":protected]=> // string(15) "protected_value" // ["private_property":"aClass":private]=> // string(17) "new_private_value" // ["public_property"]=> // string(12) "public_value" // } 




Conclusion



Using this or that case, remember that in this way you faithlessly intrude into the protected area of ​​the object, thereby bypassing all the protection in the form of protected or private, and the object will not even know about it. Therefore, if there is a possibility, it is better to make special access methods.

Source: https://habr.com/ru/post/138102/



All Articles