The harvester pattern applied

The example below demonstrates how the harvester object, in this case the EventManager, checks the existence of the getEvents() method and uses it to collect data from other objects.

This might not look any different than the previous example and in fact it has the same result. The main difference is that the EventObjects aren't aware of the EventManager object and don't have to be of a specific type to be able to offer events to the manager object. This provides loose coupled architecture that allows a variety of objects with different types to interact with another object just by adding a method.

 * Simple class to demonstrate method harvesting
 * @author Rob Theeuwes - ThiOz.com
 */
class EventManager
{
    
    private $_aEvents = array();
    
    public function __construct()
    {
        
    }
            
    public function addEventObject($oEventObject)
    {
        if(method_exists($oEventObject, 'getEvents'))
        {
            $aEvents = call_user_func_array(array($oEventObject, 'getEvents'), array());
            foreach($aEvents as $sEvent => $sCallback)
            {
                if(!isset($this->_aEvents[$sEvent]))
                {
                    $this->_aEvents[$sEvent] = array();
                }
                
                $this->_aEvents[$sEvent][] = array('object' => $oEventObject, 'callback'=>$sCallback);
                
            }
            
        }    
    }
    
    public function fireEvent($sEvent)
    {
        if(isset($this->_aEvents[$sEvent]))
        {
                $aHandlers = $this->_aEvents[$sEvent];
                foreach($aHandlers as $aHandler)
                {
                    $oEventObject = $aHandler['object'];
                    call_user_func_array( array($oEventObject, $aHandler['callback']), array() );
                }
        }        
    }
}

class MailEventObject
{
    function __construct()
    {
            
    }
    
    function getEvents()
    {
        return array( 'mail_sent' => 'onMailSent' );
    }
    
    function onMailSent()
    {
        echo 'a mail was printed';
    }
}

/*
 * the PrintEventObject does not have the getEvents method so it wil be discarded by the EventManager
 */
class PrintEventObject
{
        
    function onMessagePrint()
    {
        echo 'a message was printed';
    }
    
}

class SomeOtherObject
{
    
    function getEvents()
    {
        return array('some_event', 'onEvent');
    }
    
    function onEvent()
    {
        echo 'this event fired too';    
    }
    
}

$oManager = new EventManager();

$oMailEvent = new MailEventObject();
$oPrintEvent = new PrintEventObject();

$oManager->addEventObject($oMailEvent);
$oManager->addEventObject($oPrintEvent);

$oManager->fireEvent('mail_sent');
$oManager->fireEvent('message_print');
  ?>