Dynamic Properties in PHP and StdClass
Languages like JavaScript and Python allow object instances to have dynamic properties. As it turns out, PHP does too. Looking at the official PHP documentation on objects and classes you might be lead to believe dynamic instance properties require custom __get
and __set
magic methods. They don't.
Simple, Built-in Dynamic Properties
Check out the following code listing:
class DynamicProperties { }
$object = new DynamicProperties;
print isset($object->foo) ? 't' : 'f'; // f
// Set Dynamic Properties foo and fooz
$object->foo = 'bar';
$object->fooz = 'baz';
// Isset and Unset work
isset($object->foo); // true
unset($object->foo);
// Iterate through Properties and Values
foreach($object as $property => $value) {
print($property . ' = ' . $value . '<br />');
}
// Prints:
// fooz = baz
Using the built-in dynamic instance properties is an order of magnitude faster (30x, by my profiling) than using magic __get
and __set
methods. Built in dynamic property accesses happen without invoking a method call back to PHP script.
So when does it make sense to use __get
and __set
? If you need more complex behavior, like calculated properties, you must use __get
and __set
. Also, as an astute comment points out, if you would prefer not to have dynamic properties on a class you can throw errors from __get
and __set
.
StdClass: Anonymous Objects
Sometimes all that is necessary is a property bag to throw key value pairs into. One way is to use array, but this requires quoting all keys. Another way is to use dynamic properties on an instance of StdClass. StdClass is a sparsely documented class in PHP which has no predefined members.
$object = new StdClass;
$object->foo = 'bar';
json_encode($object);
Next I'll touch on the SPL's Countable and ArrayAccess as a means of being able to accomplish the following in PHP:
class MyClass implements Countable, ArrayAccess { ... }
$myObject = new MyClass();
// Using array access notation
$myObject[0] = 'hello';
$myObject[1] = 'world';
$myObject['foo'] = 'bar';