Listener/Observer Model in PHP I've taken a look at the SPL Listener/Observer model but found that it doesn't work when using static methods. So I wrote my own but it's very simply.  Can anyone suggest ways to make it more like the Model standards and if there is anything obvious that I've missed?

&lt;?php
namespace modular\core;

class Listeners{
    private static $listeners = array();
    private static $triggered = array();
    private static $broadcasts = array();

    public static function attach($event, $key, $callback){
        $config = \modular\core\ModuleLoader::getModuleConfig($key);
        $config['instance'] = get_class($callback[0]);
        $callback['config'] = $config;
        static::$listeners[$event][md5($event.$key)] = array('module' =&gt; $key, 'callback' =&gt; $callback);
    }

    public static function detach($event, $key, $callback){
        unset(static::$listeners[$event][md5($event.$key)]);
    }

    public static function listeners($event = ''){
        return ($event == '') ? static::$listeners : static::$listeners[$event];
    }

    public static function listenersRegistered(){
        return static::$listeners;
    }

    public static function listenersTriggered(){
        return static::$triggered;
    }

    public static function getBroadcasts(){
        return static::$broadcasts;
    }

    public static function broadcast($event){
        $rendered = \modular\core\Renderer::rendered();

        $caller = debug_backtrace();//true, 1 - check version and implement this
        array_shift($caller);

        static::$broadcasts[$event][] = $caller;

        if(isset(static::$listeners[$event])){
            if(!$rendered)
                ob_start();

            foreach(static::$listeners[$event] as $listener){
                $myEvent = (\modular\core\Router::routed() ? ($listener['module'] == \modular\core\ModuleLoader::getActiveModule()) : true);
                if($myEvent){
                    static::$triggered[$event] = $listener;
                    $test = \modular\core\ModuleLoader::runModule($listener);
                }
            }

            if(!$rendered)
                ob_end_clean();
        }
    }
}
?&gt;


The code to add a listener: 

public static function addListener($event, $callback){
        $modules = \modular\core\ModuleLoader::getModules();

        if(($key = array_search($callback[0], $modules)) !== false){
            \modular\core\Listeners::attach($event, $key, $callback);
        }
        else{
            //problem - object not found...
        }
    }

_::addListener('pre-render', array(&amp;$this, 'init'));


Callback is a callback function set as an array to specify the instance 

The MD5 is used to combine both the $event and $key as a $key (module) can register to multiple events and vice-versa.

Broadcast is purely checking if any output has already occurred, if not then block all output if so then allow output whilst it calls the module callback method.

Because it's a framework static methods are used as my preferred method to access a class from multiple classes without having to worry about creating variables of instances that I either have to remember globally or re-instantiating the class constantly.
Because it's a framework static methods are used as my preferred method to access a class from multiple classes without having to worry about creating variables of instances that I either have to remember globally or re-instantiating the class constantly.


I don't do php, but I'll give this one a try.

Being a framework shouldn't be a reason to prefer static methods everywhere.

The Observer Pattern can be depicted as follows:




  I've taken a look at the SPL Listener/Observer model but found that it doesn't work when using static methods.


There's a reason for that. If I read the code correctly, then when you have a class called SubjectA, and register 3 observers statically, every single instance of SubjectA will have the 3 observers registered; this is unlikely to be the intended behavior (not to mention threading issues), and it's only happening because of the static stuff.1

It looks like your Listeners class is intended to be used in object composition, like, you'll create a Car class that has a Listeners instance, and you'll register listeners for an Explode event. Then you might have a Dog class that has a[nother] Listeners instance, and you'll register listeners for a Bark event. If I assessed the situation correctly, that will give you a barking Car and an exploding Dog, on top of the expected events.

1 that is, if static in php has the same meaning as static in c#, which I'm assuming here.