Event Handling Classes in PHP

Been looking at what Java and .NET do in regard to event handling in web applications.

To date, most PHP apps which get into OO use a fusebox like approach, in that one script (usually index.php) is used to handle events - all things begin with index.php. That’s fine but I’m wondering if there’s a more generic way to do it - a class you can simple instantiate from anywhere to handle events?

Some resources for Java and .NET that discuss this;

http://www.devarticles.com/content.php?articleId=172&page=1

The way I see it in PHP is something like this;

An EventRegister class (using a Singleton pattern) which any object can use to register events with.

An EventHandler class, which checks $_GET, $_POST, $_COOKIE and $_FILE for events registered with the EventRegister class.

The next (tough) question is how the EventHandler can fire off the event itself (e.g. an object which validates incoming $_POST data then another object which INSERTs into a database).

Any ideas? My attempts at writing the classes so far have left me deeply confused.

This could be interesting if you could make a way to pass an event queue to a script, there be having an unlimited order of events that can be passed.

If you could do this you could sort of extend the single request-response nature of a HTTP request.

Maybe… I don’t know…

Definately. Hadn’t looked it that way but thinking about sessions and serialize objects, should be very possible.

I’ll post the code I’ve been playing with later (don’t have it to hand right now).

Harry,
I would not access the _POST _GET var directly but I will access them using a class.
Something like the HttpRequest from Java.

In my app I have something like:


Class HttpRequest
{
   function getMethod();
   function getParam( $name );
   function getRequestUri();
   //etc
}

print $request->getParam( 'page' );

Just an idea.

About Event handling I had something similar on a C++ application that uses a GUI.

There was an Event class which is the event itself.
There was an EventManager class which was the queue of events.
There was a class Object that have a method called Event.
Every element on the screen had an Event method.

So the code looked something like:

// Create an event and put it in the queue
eventManager->Put( new Event( L_SELECT ) );

// The event is passed to the object
myObject->Event( eventManager->Get() );

It has been past many years since I used that app, so these are far memories.

I have no idea if it can be of some utility for you,
it’s just a feedback from me.

:slight_smile:
pippo

Harry: its ironic, I was thinking about doing something just like this, after a discussion I was having with Vincent on IRC a couple days ago.

I was actually thinking of how I could make my quick/dirty template system better, and more robust/OO ( its really just a quick hack right now :wink: )

what I was thinking of doing, will work something like this:


// class that handles any event
    class MyEvent extends EventHandler {
        // override the default function, which is called by the PageClass
        function raise( $param_array ) )
            ...
            return( $display ); // what will be displayed on the page
        }
    }
    $page = new PageClass( $template_file );
    $page->AddHandler( $event, new MyEvent() );
    // $event is something which is actually defined in the template
    $page->show(); // edit: a method to display would be helpfull too :P (havent been awake long)

ofcourse, I’m open to any suggestions :slight_smile:

OK - got to rush - just splatting these (untested) classes down. Will explain more (handlers still required);


<?php
//: EventRegister.class.php

class EventRegister {

    /**
    * @param $events array
    * Holds registered events
    */
    var $events;

    // CONSTRUCTORS
    function EventRegister() {
        $this->events= array();
    }

    // MANIPULATORS

    /**
    * Registers an event
    * @param $eventName string. For example the <i>name</i> of
    * a $_GET variable
    * e.g. index.php?action=foo. $eventHandler="action";
    *
    * @param $eventHandler string. the name of the handler for that event
    *
    */
    function register ($eventName,$eventHandler) {
        $this->events[$eventName]=$eventHandler;
    }

    // ACCESSORS

    /**
    * Returns the parameters for an event
    * @param $eventName string.
    * @return - either array or false
    * if event does not exist.
    *
    */
    function getByName ($eventName) {
        if ( isset ( $this->events[$eventName] ) ) {
            return $this->events[$eventName];
        } else {
            return false;
        }
    }

    /**
    * Returns the complete events array
    * @return - array of events to their param names.
    *
    */
    function getAll () {
        return $this->events;
    }
}

class EventSingleton {

    /**
    * @param $instance object
    * Holds and instance of the EventRegister class
    */
    static $instance;
    /**
    * Creates a new EventRegister object if none found
    * @return object
    */
    function EventSingleton () {
        if(!isset($this->instance)) {
            $this->instance =& new EventRegister();
        }
    }

    /**
    * Returns the EventRegister object
    * @return object
    */
    function getReg() {
        return $this->instance;
    }
}
?>


<?php
//: EventListener.class.php

include_once('EventRegister.class.php');

class EventListener {

    var $eventRegister;

    var $get;

    // CONSTRUCTORS
    function EventListener() {
        $eventReg=& new EventSingleton;
        $this->eventRegister=$eventReg->getReg();
        $this->findCurrentEvents();
    }

    // MANIPULATORS

    /**
    * Searches the $_GET global looking for registered events
    * and stores in a local variable for triggering
    * @return - no return value
    *
    */
    function findCurrentEvents () {
        $events= $this->eventRegister->getAll();
        foreach ( $events as $eventName to $eventHandler ) {
            if ( isset ( $_GET[$eventName] ) ) {
                $this->get[$eventName]=$eventHandler;
            }
        }
    }

    // ACCESSORS

    /**
    * Triggers handler classes from current events
    * @return - no return value
    *
    */
    function trigger () {
        foreach ( $get as $eventName to $eventHandler ) {
            $eventHandler=& new $eventHandler;
            $eventHandler->respond();
        }
    }
}
?>

Handlers would be “wrapper” classes for existing classes to make them behave.

Another class for Pagoda? :slight_smile:

I really like this idea of an Application with a persistant state that responds to events… NICE!

A also like your idea of Handlers being ‘wrappers’. This could come in real handy to adapt current scripts into a sort of ‘middleware’ for an application.

When i get some time i’d really like to explore this concept further…

OK - first changing the trigger method in the listener class above;


    function trigger () {
        if (isset($this->get)) {
        foreach ( $this->get as $eventName => $eventHandler ) {
            $$eventHandler=& new $eventHandler;
            $$eventHandler->respond();
        }
        } else {
            // Do default handler if no events
            $defaultHandler=& new DefaultHandler;
        }
    }

Note the variable variable now (like I said - haven’t been tested yet.

Here’s my guess at how this might work;

Two handlers;


<?php
include_once('EventRegister.class.php');

// Kinda dodgy but how without instantiating FormHandler - better ideas?
$eventReg=& new EventSingleton;
$eventRegister=$eventReg->getReg();
$eventRegister->register('formResponse','FormHandler');

class FormHandler {

    var $response;

    function FormHandler {
        switch ($_GET['formResponse']) {
            case 'sendEmail':
                $this->sendEmail();
                break;
        }
    }

    function sendEmail () {
        // this could be invoking another class instead...
        mail ( $_POST['to'],$_POST['from'],$_POST['subject'];
        $this->response='Email sent';

    }

    function respond () {
        echo ( $this->response );
    }
}
?>

Then the default hander;


<?php
// DefaultHandler.class.php
class DefaultHandler {
    // Do default stuff here

   function respond() {
       // make whatever response
   }
}
?>

Now a script that ties it all together;


<?php
// email.php

include_once('FormHandler.class.php');
include_once('EventHandler.class.php');

include_once('EventListener.class.php');

$listener=& new EventListener;

$listener->trigger();
?>

That’s the general idea at least…

Comments (including “You’re soooo wrong” ;)) appreciated.

Still taking in pippo and AcidReigns comments. Certainly there could be some more efficient approach using inheritance and polymorphism. Wanted to avoid having to change existing classes though to provide “AddEvent” methods - perhaps that’s where polymorphism can come in…

Hey, no offense to your idea, but isn’t this a lot easier?

<?php
switch ($_GET['formResponse']) {
    case 'sendEmail':
        mail ( $_POST['to'],$_POST['from'],$_POST['subject'];
        print 'Email sent';
        break;
    default:
        //whatever
}

In my opinion, there are a few flaws floating around in an otherwise good topic.

  1. PHP is a scripting language with minimal support for OO. And, being an interpreted, run-time language, the good old “less-is-more” mentality has to prevail.

  2. It seems that truly useful event registers would have to be implemented by the application server (PHP engine, for instance) rather than wedged in by way of some overbearing PHP classes.

  3. I’m a firm believer in “the right tools for the job”, and with that said, there are plenty of scripted application servers for HTTP. Dumping HTML to a browser seems - at present - a trivial task, best handled in a simpler-is-better manner.

If you’re going to rethink the way things work (which is something I’m all for) you have to rethink the whole process. It doesn’t make sense to reinvent one facet of app servers, only to shoe-horn it into existing methodologies.

So in other words, why not a new architecture that implements HTML-inspired events straight out of the app server?

Alright! :wink:

Well I agree with you on one level, although the example you give of a switch statement lacks some ingredients event handling could deliver such as the ability to have multiple events and not to be tied to expection particular named $_GET variables, for example.

What if you have two important $_GET variables plus a cookie variable you want to response to? You’re talking multiple switch statements or if/elses.

I’m not saying I’ve got a perfect solution (probably far from it) but the idea is by wrapping up your code in a series of handlers, it could become extremely easily to reuse existing classes and handlers.

All in all, it’s a result of frustration from having built applications which ended up in giant and unwieldy conditional statements in index.php

It seems that truly useful event registers would have to be implemented by the application server (PHP engine, for instance) rather than wedged in by way of some overbearing PHP classes.

Think you’re right perhaps I don’t think the PHP group really responds to demand but rather what they’ve got time for. Some would also argue that the PHP engine should be kept free of such things.

Interesting point though, while you’re suggesting application servers - http://sdk.ez.no/sdk/ezutils - the Module Handler for example and the HTTP Object Persistance classes…

Been fooling with ezPublish alot recently, at work and at play - the current version handles events in a fairly crude way (looks for a particular filename then uses switch statements within that file) but is already excellent. You could already describe it as an application server in some senses. Version 3.0 is on the horizon and methinks it’s gonna rock!

But back to the point - if Javascript can have eventHandling, why shouldn’t PHP? And more to the point, as it’s being done in ASP.NET

  1. PHP is a scripting language with minimal support for OO. And, being an interpreted, run-time language, the good old “less-is-more” mentality has to prevail.

Alright here we go again… What is missing in PHP’s OO support according to you??

  • Multiple Inheritance
    Is considered a bad practice in OO. A form of multiple inheritance, interfaces, can be done in PHP. It just requires your (the programmer’s) discipline

  • Private / Public Properties
    No property should be public anyway, it goes against encapsulation. The whole concept of private / public properties was only introduced to make it easier for programmers. Again, with discipline, this is not a problem.

  • Multiple constructors / function overloading
    Functions in PHP accept a variable number of parameters, so this can be done.

  • Static class variables
    Can be done by using a function with a static variable or by using globals which are hidden from the rest of the code (with your discipline of course).

  • Dereferencing ($obj->getObject->function())
    Just use an extra variable, this is just something to make life a little easier, nothing more.

  • Destructors
    Those are IMHO merely for when you’re lazy. With a little discipline, you can just call a destructor function instead of it being done automatically.

My point is, with a little discipline, you can do almost exactly (correct me if I’m wrong) what you would do in a language like Java or C++ using objects.

It all depends on how you treat your code. Of course, you can go and break your own rules like encapsulation by accessing private properties directly, but then this is your problem, not the language’s problem. I believe voostind (can I get some support from you on this? :rolleyes:) once posted that even in languages like C++ it is possible to access an object’s private properties.

But we’re going way off topic, so if you want to continue the PHP OO discussion feel free to start a discussion in a new thread or something.

alright, I’ve come up with another quick & dirty, shall we say, proof of concept :slight_smile:

since my code says more than I can:
the classes
the example

now, what the example does not show, is that you do not need a template file … you can call a [untested] show( $object ) method, that takes an object that is derived from DisplyHandler, show() then calls the display( $object ) method of the DisplayHandler, which is given the current Display instance [ $object->display( $this ); ]
the Display handler can handle output in anyway it wants to … it has access to all the values [setvalue/getvalue] and it can call the callevents() method as it wishes.

comments? suggestions? flames?

That looks excellent! Still taking it in but can see how you could use objects instead of templates. Really like the mechanism for adding events. Don’t see right now how you respond to “user actions” though, such as index.php?view=page2.

Will have a play and see what happens…

Originally posted by Captain Proton
[B]

  • Multiple constructors / function overloading
    Functions in PHP accept a variable number of parameters, so this can be done.
    [/B]

Can be faked if you really need:

  1. Count number of arguments, and associate them with different functions:

class test
{
    function test()
    {
        // get number of args, place, and then build an argument list
        switch( $argTotal )
        {
            case 1:
                $this->_test1( $argString );
                    break;

             case 2:
                 $this->_test2( $argString );
        }
    }
}

This probably isn’t all that good of a solution, but if you must have it, you can I suppose

I’m thinking that this is definatley a good idea for an external extension.
Especially if persistance and object serialization is added.

I also have been thinking that it would be cool if you could register events with a XML-RPC or some other remote call as the handler.

AcidReign i like that code, but i think it would be better to abstract the event registering/executing stuff totally seperate from the display (although i can see how that could be a particular event) and then implement the presentation layer as events (although i already said that is kinda what you are doing)

Anyway i think that if persistance is the name of the game then it would be good to do a C extension.

OK - finished of the “first version” based on what I started with (attached as Zip with a mini demo site included).

Here’s how it can be used now;


<?php
// Include the EventRegister and Listener
include_once('EventRegister.class.php');
include_once('EventListener.class.php');

// Include the custom handlers
include_once('NavHandler.class.php');
include_once('FormHandler.class.php');

$eventReg=& new EventRegister;

// Regiser handlers
$eventReg->register('view','NavHandler');

// Notice - FormHandler registered twice for;
// index?formResponse=whatever and
// index?action=whatever
$eventReg->register('formResponse','FormHandler');
$eventReg->register('action','FormHandler');

// Fire up the listener, passing it the register and setting
// the default handler to nav handler
$listener=& new EventListener($eventReg,'NavHandler');
$listener->trigger();
?>

At the moment it’s specifically geared to the $_REQUEST global - XML-RPC etc. would require some alteration…

Also it doesn’t handle multiple events well. With the demo in the ZIP, if you use “index.php?view=links&action=addComment” for example, it will look a little wierd.

Think the answer to that is rather than handlers echoing output directly, they put messages on an “event output queue” which the listener then deals with as the final step. Course when I start thinking about that, reckon this now is going too far.

The other direction to go might be using output buffering and customer error handlers - use trigger_error to activate events. Might also be interesting to use get_declared_classes() in some way - perhaps to find all the declared handlers.

Anyway - I need a break. This has all been too eventful :smiley:

Can someone please explain the purpose of events in PHP with a few senteces, what problem they have to solve? I can understand their place in the GUI side of application (in JavaScript) but not in server side. Isn’t the execution of the script only event needed (and only event that happens on server)?

Aivar

Isn’t the execution of the script only event needed (and only event that happens on server)?

Well yes but what the script actually does may vary from execution to execution, depending of things like form POSTs and links with GET variables. Perhaps this should be described more like “incoming event handling”.

Here’s one example;

http://www.site.com/index.php - the home page
http://www.site.com/index.php?view=news - site news
http://www.site.com/index.php?action=login - the action of a “login form”
http://www.site.com/index.php?update=userdetails - update your user details

And what about this;

http://www.site.com/index.php?view=news&action=login - login AND display the news

To deal with this in the index.php, you’re talking some big switch statements like;


<?php
// index.php
// using includes for demonstration purpose...

switch ( $_GET['action'] ) {
    case "login":
       include ('login.php');
    break;
    case "logout":
       include ('logout.php');
    break;
    // etc.
    default:
    break;
}

switch ( $_GET['update'] ) {
    case "userdetails":
       include ('userdetails.php');
    break;
    // etc.
    default:
    break;
}

switch ( $_GET['view'] ) {
    case "news":
       include ('news.php');
    break;
    case "guestbook":
       include ('guestbook.php');
    break;
    // etc.
    default:
       include ('home.php');
    break;
}

That’s only to handle a few “incoming” events. What happens in an application where there’s a lot of room for user interaction? There’s other ways to write the above code, using arrays for example, which will be more compact to read but amounts pretty much to the same thing - the whole app depends on this single script being correct, even when it becomes highly complex.

The other approach to the problem is to specify particular variable names for example;

http://www.site.com/index.php?application=forum&module=administration&event=deletepost

That’s fine in a way, but then all your code needs to conform to this standard - often a problem in intergrating old code an different applications. Also you’re generally tied to a single script (index.php) being the “traffic cop” for your application.

I also think that it is the order of events that can make this system eventful :slight_smile: . You could have your application respond to the an unlimited number of events in any order.

Usually if you follow the ‘old’ system that Harry pointed out then the order of execution of a script is hard-coded (at least to some extent). This ‘new’ way you could get different responses by differing the order of event execution.