PHP Prototyping
Apr 20
So its been a while. Change of job, new babies, and other random events have filled my time. I think I’m ready to start blogging again and I’m hoping that this one really interests everyone.
The one thing I like the most about JavaScript is prototyping. It kind of annoys me that PHP doesn’t have this function, but there isn’t really anything we (non-core developers) can do about that. I have come up with a class that allows for a SEMI prototyping solution. Now I have seen elsewhere that people have put together a class that will let you add closures and use them as functions but this isn’t really prototyping as you cannot modify existing class methods. So this solution is something that I whipped up in about 30 minutes, and I’m very interested in people tweaks, and suggestions. Here’s how it works…
Basic loading for building a class on the fly
$test1 = new Prototype();
$test1->prototype('testingFunction', function() use($test1){
echo 'Hi!';
});
$test1->testingFunction(); // Echos Hi!
Now lets actually extend a class that exists. Here we will extend a method of the class but then call it right after our extension.
$test2 = new Prototype('DateTime');
$test2->prototype('setDate', function() use($test2) {
echo 'Hi!2';
$test2->parentCall('setDate', func_get_args());
});
simple right?
Okay enough examples… Here is the class itself.
<?php
/**
* Mock prototyping setup for PHP
*
* @author Christian South [christian (at) nopantssoftware (dot) com]
* @category Prototype
* @license New BSD License
* @copyright Copyright (c) 2011 No Pants Software
*/
class Prototype
{
/**
* Extended Class
* @var mixed
*/
protected $_extendedClass;
/**
* Extension methods
* @var array
*/
protected $_extensions = array();
/**
* Call function
*
* @param string $functionName
* @param array $args
* @return mixed
*/
public function __call($functionName, $args)
{
if(isset($this->_extensions[$functionName])) {
return call_user_func_array($this->_extensions[$functionName], $args);
} elseif(method_exists($this->_extendedClass, $functionName)) {
return call_user_func_array(array($this->_extendedClass, $functionName), $args);
}
throw new Exception('Unable to find method: '.$functionName);
}
/**
* Class Constructor
*
* @param mixed $className
* @return void
*/
public function __construct($className = null)
{
if(null !== $className) {
if(is_string($className)) {
$this->_extendedClass = new $className();
} else {
$this->_extendedClass = $className;
}
}
}
/**
* Call a parent function
*
* @param string $functionName
* @return mixed
*/
public function parentCall($functionName)
{
$args = func_get_args();
array_shift($args);
return call_user_func_array(array($this->_extendedClass, $functionName), $args[0]);
}
/**
* Add extension Method
*
* @param string $functionName
* @param Closure $function
* @return Prototype
*/
public function prototype($functionName, Closure $function)
{
$this->_extensions[$functionName] = $function;
return $this;
}
}
Again, I’m interested in every ones thoughts on tweaks and expansions on this. And even things that you see wrong.

Yeah, I’ve played with something similar a while ago http://activedeveloper.info/prototype-based-object-oriented-programming-in-php
@mhitza – the point of this one was not just to allow for prototyping, but prototyping on internal classes. Thanks for the link though.
interesting as actually it looks like the IT crowd is, on the contrary, trying to get rid of js prototyping (ie. coffescript)
@gino I seriously doubt that JS will ever move away from prototyping. It is such a huge part of the projects that dominate the JS world for web developers. (jQuery, Prototype, etc). These projects use prototyping for extensions as well the code the project runs on.