Class Proxy in PHP

Posted May 14, 2010

One of the nice things with PHP is that if you include a file from within a class method, that included file can use "$this" to access the class which included it. Very handy.

However, today I wanted to make it even easier - I wanted the loading of content to exist in a separate class, but I still wanted the included file to be able to access the top-most class which needed it. To compound it, I also had another intermediary class I wanted to expose directly to the included file (for no other reason than I'm lazy).

Thanks to PHP 5's magic methods, I was able to develop a "Proxy" class:

<?php
/**
 * This class provides a dynamic proxy whereby objects may be registered,
 * and any attempt to either invoke a method or access a property would
 * bubble through these objects until one can be handled.
 *
 * @author Nathan Crause <nathan@digitalcove.ca>
 */
class Proxy {

    private $objects;

    public function add(&$object) {
        if (!is_object($object)) throw new Exception('Expected object, received '.gettype($object));

        $this->objects[] = $object;
    }

    public function  __get($name) {
        foreach ($this->objects as $object) {
            if (property_exists($object, $name)) {
                return $object->$name;
            }
        }

        throw new Exception("Unknown property '$name'");
    }

    public function  __call($name,  $arguments) {
        foreach ($this->objects as $object) {
            if (method_exists($object, $name)) {
                return call_user_func_array(array($object, $name), $arguments);
            }
        }

        throw new Exception("Unknown method '$name'");
    }

}
?>

This simple bit of code did what I needed. Now I can do this:

 

<?php
class Loader extends Proxy {
    public function load($filename) {
        include($filename);
    }
}

class A {
    public function doSomething() {
    }
}

class B {
    public function doAnotherThing() {
    }

    public function load() {
        $loader = new Loader();

        $loader->add(new A());
        $loader->add(new B());

        $loader->load('test.php');
    }
}
?>

 

<?php
// test.php
$this->doSomething();
$this->doAnotherThing();
?>

Comments

There are no comments for this post.

No comments found

Add comment

Visit my Friends and Family

If you've enjoyed my site, please take a moment to visit my friends and family, many of whom have some interesting insights, and entertaining thoughts and ideas.