Javascript Prototype Behaviour in PHP

One of the “neat” things in Javascript is you are able to dynamically add or change methods of a class and automatically update every instance of that class. Some of the things I usually find useful are adding to the String class, like so:

String.prototype.htmlSpecialChars = function() {
    return this.replace(/\</g,'&#060;').replace(/\>/g,'&#062;');
}
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, '');
}

Obviously we cannot do this in PHP, and why would we, right? However we can emulate this behaviour to a certain extent using my “neat” little Prototype class. With this Prototype class we can dynamically add properties and methods to any class, and they will be inherited by all instances of that class. Let’s look at the following “normal” PHP code.

<?php

class Person extends Prototype
{
    public $name;
    public $gender;

    public function gender()
    {
        printf("%s is %s\n", $this->name, $this->gender);
    }
}

$matt = new Person;
$matt->name = 'Matt';
$matt->gender = 'male';
$matt->gender();

// Matt is male

?>

Now, there is nothing magical or out-of-the-ordinary going on here. We just instantiate the Person class and setup some properties. Calling the gender() method outputs a nice little string for us.

However, you see that the Person class is actually a child of the Prototype class. This will allow us to do some of that “neat” Javascript stuff. Using Prototype, let us expand the Person class to add an $age property and an age() method to output a nice string. Like so:

<?php

Person::add_property('age');
Person::add_method('age', 'printf("%s is a %d year old %s\n", $this->name, $this->age, $this->gender);');

$matt->age = 28;
$matt->age();

// Matt is a 28 year old male

?>

Now all instances of Person inherit the $age property and age() method. So we can create a new Person, Susie, and this object will now have the age stuff.

<?php

$susie = new Person;
$susie->name = 'Susie';
$susie->gender = 'female';
$susie->age = 21;
$susie->age();

// Susie is a 21 year old female

?>

One limitation of the Prototype class though, is you cannot overload a current method. So the following code, that attempts to overload the gender() method, will not work.

<?php

Person::add_method('gender', 'printf("%s is a %d year old %s\n", $this->name, $this->age, $this->gender);');

$matt->gender();

// Matt is male

?>

There are also many, many, many other problems with this Prototype class. Some of which are:

This class was just an experiment to see if it was at all possible to implement something like Javascript’s prototype behaviour in PHP with out using the Runkit PECL extension. I had no intention of actually making this usable in production, for many reasons; Although it was fun.