Class Object to create objects of type Object, in a dynamic way, with magic methods
As pointed out before, in a comment, non-magic methods in a class shouldn't be prefixed with __.

Since they are private, they are prefixed with _.



Closures are a really nice feature that came with PHP5.3, and they weren't being used to their full potential.

Closures have the method bindTo, which generates a new Closure binded to that object.
This allows to use the variable $this inside the Closure.
It helps the fellow programmers that decide to use this to write in a more natural way.
The best part is that there are no kludges needed!

The method _run_magic_method() will look like this:

    private function _run_magic_method( $method, $args=null )
    {
        $obj = (object)$this-&gt;props;

        if( is_a( $this-&gt;methods[$method], 'Closure' ) )
        {
            $return = call_user_func_array( $this-&gt;methods[$method]-&gt;bindTo( $obj ), (array)$args );
        }
        else
        {
            $return = call_user_func_array( $this-&gt;methods[$method], array_merge( array(&amp;$obj), (array)$args ) );
        }
        $this-&gt;props = (array)$obj;
        return $return;
    }


Since objects are passed as references in PHP5, all changes are reflected on the properties.



The final code:

&lt;?php

    class Object {
        private $props = array();
        private $methods = array(
            '__construct'=&gt;null,
            '__get'=&gt;null,
            '__set'=&gt;null,
            '__isset'=&gt;null,
            '__unset'=&gt;null,
            '__toString'=&gt;null
        );
        private function _run_magic_method( $method, $args=null )
        {
            $obj = (object)$this-&gt;props;

            if( is_a( $this-&gt;methods[$method], 'Closure' ) )
            {
                //Inside the closure, the $this will be changing the parent $this-&gt;props
                $return = call_user_func_array( $this-&gt;methods[$method]-&gt;bindTo( $obj ), (array)$args );
            }
            else
            {
                $return = call_user_func_array( $this-&gt;methods[$method], array_merge( array( &amp;$obj ), (array)$args ) );
            }

            $this-&gt;props = (array)$obj;
            return $return;
        }
        private function _has_magic_method( $method )
        {
            return isset( $this-&gt;methods[$method] ) &amp;&amp; is_callable( $this-&gt;methods[$method] );
        }
        function __construct( array $props )
        {
            foreach( array_keys( $this-&gt;methods ) as $method )
            {
                if( isset( $props[$method] ) )
                {
                    $this-&gt;methods[$method] = $props[$method];
                    unset( $props[$method] );
                }
            }
            $this-&gt;props = $props;
            if( $this-&gt;_has_magic_method( '__construct' ) )
            {
                $this-&gt;_run_magic_method( '__construct' );
            }
        }
        function __get( $key )
        {
            if($this-&gt;_has_magic_method('__get' ) )
            {
                return $this-&gt;_run_magic_method( '__get', array($key) );
            }
            else
            {
                return $this-&gt;props[$key];
            }
        }
        function __set( $key, $value )
        {
            if( $this-&gt;_has_magic_method( '__set' ) )
            {
                $this-&gt;_run_magic_method( '__set', array( $key, $value ) );
            }
            else
            {
                $this-&gt;props[$key] = $value;
            }
        }
        function __isset( $key )
        {
            if( $this-&gt;_has_magic_method( '__isset' ) )
            {
                return $this-&gt;_run_magic_method( '__isset', array($key) );
            }
            else
            {
                return isset( $this-&gt;props[$key] );
            }
        }
        function __unset( $key )
        {
            if( $this-&gt;_has_magic_method( '__unset' ) )
            {
                return $this-&gt;_run_magic_method( '__unset', array($key) );
            }
            else
            {
                unset( $this-&gt;props[$key] );
            }
        }
        function __call( $key, $args )
        {
            if( isset( $this-&gt;props[$key] ) &amp;&amp; is_callable( $this-&gt;props[$key] ) )
            {
                return call_user_func_array( $this-&gt;props[$key], $args );
            }
            else
            {
                trigger_error( 'The key "'.addslashes($key).'" is not a callable', E_USER_ERROR );
            }
        }
        function __toString( )
        {
            if( $this-&gt;_has_magic_method( '__toString' ) )
            {
                return $this-&gt;_run_magic_method( '__toString' ) . '';
            }
            else
            {
                trigger_error( 'There is no defined __toString method', E_USER_ERROR );
            }
        }
        private function _keys()
        {
            return array_keys( $this-&gt;props );
        }
        static function keys( Object $obj=null )
        {
            if( $obj === null )
            {
                return array();
            }
            else
            {
                return $obj-&gt;_keys();
            }
        }
    }


Example of execution:

$obj = new Object(array(
    'a'=&gt;5,
    '__get'=&gt;function($k){
        echo 'Getting the value from the key \'',$k,'\'', PHP_EOL;
        return $this-&gt;{$k};
    },
    '__set'=&gt;function($k,$v){
        echo 'Setting a value on the key \'',$k,'\'', PHP_EOL;
        $this-&gt;{$k}=$v;
    }
));

/*
 *Should output:
 *
 * Getting the value from the key 'a'
 * 5
 * Setting a value on the key 'b'
 * Getting the value from the key 'b'
 * 6
 *
 */