Hi guys, as you probably know, PHP 5.3.0 has great chances of bringing anonymous functions and closures to PHP. So I decided to play a little bit with this and inspired by the Javascript language I've tried to implement some kind of prototypal functionality. Although on the RFC page it is listed as a misconception the thing that I've done, I felt that I should try it.

So here's what I've done so far:

Code PHP:
<?php
 
class Object
{
    /**
     * Holds functions assigned to PROTOTYPE
     */
    protected static $_classMethods    = array();
 
    /**
     * Holds properties assigned to PROTOTYPE
     */
    protected static $_classProperties = array();
 
    /**
     * Holds functions assigned to THIS instance
     */
    protected $_instanceMethods        = array();
 
    /**
     * Holds properties assigned to THIS instance
     */
    protected $_instanceProperties     = array();
 
    /**
     * Flag that tells whether to assign to PROTOTYPE or to INSTANCE
     */
    protected $_usePrototype = false;
 
 
    public function __get($property)
    {
        if ($property === 'prototype') {
            $this->_usePrototype = true;
            return $this;
        } else {
            if (array_key_exists($property, $this->_instanceMethods)) {
                return $this->_instanceMethods[$property];
            }
            if (array_key_exists($property, $this->_instanceProperties)) {
                return $this->_instanceProperties[$property];
            }
            if (array_key_exists($property, self::$_classMethods)) {
                return self::$_classMethods[$property];
            }
            if (array_key_exists($property, self::$_classProperties)) {
                return self::$_classProperties[$property];
            }
 
            return $this->$property;
        }
    }
 
    public function __set($property, $value)
    {
        if ($property === 'prototype') {
            throw new Exception('Cannot assign to prototype');
        }
 
        if ($this->_usePrototype) {
            if ($value instanceof Closure) {
                self::$_classMethods[$property] = $value;
            } else {
                self::$_classProperties[$property] = $value;
            }
 
            $this->_usePrototype = false;
        } else {
            if ($value instanceof Closure) {
                $this->_instanceMethods[$property] = $value;
            } else {
                $this->_instanceProperties[$property] = $value;
            }
        }
    }
 
    public function __unset($property)
    {
        unset($this->_instanceMethods[$property]);
        unset($this->_instanceProperties[$property]);
        unset(self::$_classMethods[$property]);
        unset(self::$_classProperties[$property]);
    }
 
    public function __call($method, $args)
    {
        $args = array($this) + $args;
 
        if (array_key_exists($method, $this->_instanceMethods)) {
            return call_user_func_array($this->_instanceMethods[$method], $args);
        }
        if (array_key_exists($method, self::$_classMethods)) {
            return call_user_func_array(self::$_classMethods[$method], $args);
        }
 
        return call_user_func_array(array($this, $method), $args);
    }
}

Examples:

Code PHP:
<?php
 
$A = new Object;
$A->prototype->foo = function($this) {
    return 'foo in prototype';
};
 
$A->prototype->bar = 'bar in prototype';
 
$A->foo = function($this) {
    return 'This should only be in $A';
};
 
echo $A->foo();
echo '<br>';
echo $A->bar;
echo '<br><br><br>';
 
 
$B = new Object;
echo $B->foo();
echo '<br>';
echo $B->bar;
echo '<br>';
$B->foo = function() {
    return '<b>foo of instance B</b>';
};
$B->bar = '<b>bar of instance B</b>';
echo $B->bar;
echo '<br>';
echo $B->foo();
 
 
echo '<br><br><br>';
echo $A->foo();
echo '<br>';
print_r($A->foo);
 
 
$B->prototype->baz = function() {
    return 'Hello, I\'m baz';
};
 
$A->foo;
 
echo '<br><br><br>';
echo $A->baz();
echo '<br>';
echo $B->baz();

One WTF factor of the above is that the instance variable "$this" is passed as a first argument to the functions and not already available. It's a little bit Pythonic I think.

So, what do you think? I hope you have a snapshot of PHP 5.3.0 from http://spans.php/net so that you can play a bit with these, they're great and we may provide some valuable feedback to the devs. I can't wait for this version to go mainstream. Closures + namespaces + phar will totally change the way we do PHP. Yet, one question bothers me... who needs the dollar anymore?!