Dynamic Properties in PHP and StdClass

Written by Kris on November 27th, 2008

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';

Thanks to the folks pointing out that you don’t need to extend from StdClass in order to have dynamic properties!

8 Comments so far ↓

  1. Nov
    27
    1:26
    PM
    Wayne

    Dynamic instance properties can be set on any class irregardless of whether or not they extend from stdClass. Declaring properties is entirely optional in PHP and always has been.

    Try your BestDynamicProperties example without extending from stdClass and you’ll see that you get exactly the same result. Now try adding properties to any other PHP class and you’ll notice that works as well. stdClass is just an empty class, it has no special abilities.

    If you don’t want dynamic properties on your classes (I usually don’t to cut down on typos going unnoticed), you can define the __set() magic method to throw an exception.

  2. Nov
    27
    2:30
    PM
    Scott

    this is great, I didn’t know about stdClass. Where did you find the docs? the only mention I can find on php.net is “The name stdClass is used internally by Zend and is reserved. You cannot have a class named stdClass in PHP.”

  3. Nov
    27
    2:35
    PM
    duke

    Instead of :
    class DynamicProperties extends StdClass { }
    $object = new DynamicProperties;

    You can do just:

    class foo {};
    $object = new foo();

    and the rest of your code still works. No need to extend stdClass at all.

  4. Nov
    27
    6:15
    PM
    Kris

    @Duke, @Wayne – Thanks for the heads up. I’ve corrected the post. Amazing the range of things PHP doesn’t make obvious in the official documentation. I’ve been using __get and __set in simple dynamic properties cases for years.

    @Scott – StdClass is neat and nebulous. There really isn’t much about it on the net. It has been claimed to be the base class for all other classes in PHP but the following code bit returns false:


    echo $b instanceof stdclass ? 'yes' : 'no'; // prints 'no'

  5. Jan
    26
    5:54
    PM
    Web development

    class foo {};
    $object = new foo();

    try above

  6. Apr
    24
    8:17
    PM
    ian

    had too google far & wide to find your piece. any idea why this isn’t documented in php.net? if it’s a feature, it should be documented, but if not, it’s a bug and ought to be fixed. it certainly gives the lie to the often-repeated advice to look it up in the php documentation.

  7. May
    9
    12:51
    AM
    m rahman

    Sometimes you need declaring objects on the fly just to hold abstract members, say for packing. To use $object = new foo(); you should have declared class foo{}, while you can just object=new stdclass;

  8. Jul
    9
    11:16
    PM
    William

    If you want to set multiple properties on a single line, you can do:

    $object = (object)array(’key’ => ‘value’, ‘key2′ => ‘value2′);

    The object created will be an stdClass instance.

Spruce up your comments with
<a href="" title=""><abbr title=""><acronym title=""><b><blockquote cite=""><cite><code><del datetime=""><em><i><q cite=""><strike><strong>
New comments are moderated before being shown * = required field

Leave a Comment





1 Trackbacks / Pingbacks

  1. Rob’s Blog » Blog Archive » MySQLi vs PDO