PHP5 Klasse

Pherseus

Erfahrenes Mitglied
Hi, bin auf der suchen nach einer php5 Klasse, welche die neuerungen Verwendet. Was die Klasse macht ist im Grunde egal. Es geht mir nur um den Einsatz der neuen PHP5 OOP funktionen.
 
Öhhm ... naja ... es gibt da ziiieeeemlich viele Neuerungen. Ein paar wenige habe ich in einem kleinen EventHandler System mal implementiert:

PHP:
<?php
class CB_EventHandler {
	private $eventStack;
	private $processOutput = array();
	
	private static $listenerCounter = 0;
	private static $eventsThrown    = 0;
	
	public function __construct() {
		$this->eventStack = array();
	}
	
	/**
	 * CB_EventHandler::addListener()
	 * 
	 * @param $event
	 * @param $callbackInfo
	 * @return 
	 **/
	public function addListener(CB_EventListenerAPI $listener) {
		$this->eventStack[$listener->getListenerEvent()][] = $listener;
		$this->listenerCounter++;
	}
	
	/**
	 * CB_EventHandler::throwEvent()
	 * 
	 * @param $event
	 * @param $eventInformation
	 * @return 
	 **/
	public function throwEvent(CB_Event $event) {
		$eventID = $event->getEventID();
		
		if(is_array($this->eventStack[$eventID])) {
			foreach($this->eventStack[$eventID] as $listener) {
				$output = $listener->processOnEvent($event);
				
				if($output != false) {
					$this->processOutput[] = $output;
				}
			}
		}
		
		$this->eventsThrown++;
	}
	
	public function getProcessOutput() {
		return $this->processOutput;
	}
}

/**
 * CB_Event
 * 
 * @package CB_Event
 * @author FoG
 * @copyright Copyright (c) 2004
 * @version $Id: CB_Event.class.php,v 1.1 2005/06/11 14:10:53 jstoeber Exp $
 * @access public
 **/
class CB_Event {
	private $eventID;
	private $eventInformation;
	
	/**
	 * CB_Event::__construct()
	 * 
	 * @param $eventID
	 * @param $eventInformation
	 * @return 
	 **/
	public function __construct($eventID, $eventInformation) {
		$this->eventID = stripslashes($eventID);
		
		if(is_array($eventInformation)) {
			$this->eventInformation = $eventInformation;
		}
	}
	
	/**
	 * CB_Event::getEventID()
	 * 
	 * @return 
	 **/
	public function getEventID() {
		return $this->eventID;
	}
	
	/**
	 * CB_Event::getEventData()
	 * 
	 * @return 
	 **/
	public function getEventData() {
		return $this->eventInformation;
	}
}
?>

In dieser Klasse sieht man die Verwendung von den Sichtbarkeitsmodifikatoren. Da ich seltener mit Vererbung arbeite ist protected nicht so relevant bei mir. Du kannst hier Klassenvariablen sehen, die zählen, wie viele Events während der Laufzeit ausgeworfen wurden.
Bei den Funktionsdefinitionen sieht man Class Type Hints im Einsatz.

Des weiteren brauch ich für die einzelnen Event Listener ein Interface. Alle EventListener müssen dieses Interface implementieren. In der Klasse CB_EventHandler nimmt die Methode addListener nur Objekte entgegen, die das Interface CB_EventListenerAPI implementiert haben:

PHP:
<?php

interface CB_EventListenerAPI {
	/**
	 * getListenerEvent()
	 * auf welchen Event soll gelauscht werden?
	 * 
	 * @return string Event ID
	 **/
	function getListenerEvent();
	
	/**
	 * processOnEvent()
	 * Definiert, wie auf den Event reagiert werden soll
	 * 
	 * @param $event Event Objekt mit Informationen über den Event
	 * @return $result
	 **/
	function processOnEvent(CB_Event $event);
}
?>

Einen Test Listener habe ich auch implementiert, um die Lauffähigkeit zu prüfen:

PHP:
class CB_EventListener_article_folderDelete implements CB_EventListenerAPI {
	private $listenerID;
	private $tpl;
	
	public function __construct($tpl) {
		$this->tpl = $tpl;
		$this->listenerID = "folderDelete";
	}
	
	public function getListenerEvent() {
		return $this->listenerID;
	}
	
	public function processOnEvent(CB_Event $event) {
		$eventData = $event->getEventData();
		if($eventData['id'] != "") {
			$output = "Rubrik gelöscht";
			
			return $output;
		}
	}
}

Hinzugefügt wird der Listener in der selben Datei mit diesem Aufruf, der das neue Schlüsselwort 'instanceof' nutzt:

PHP:
if($cbEventHandler instanceof CB_EventHandler) {
	$cbEventHandler->addListener(new CB_EventListener_article_folderDelete($tpl));
}

Allerdings hab ich vieles nicht berücksichtigt wie Exceptions, die magischen Methoden __set, __get und __call sowie Destruktoren (nicht notwendig). Abstrakte Klassen brauch ich auch nicht unbedingt, könnten aber vielleicht mal als Erweiterung zur API hinzukommen. Ein Listener könnte dann von dieser abstrakten Klasse erben, womit sichergestellt ist, dass bestimmte Funktionen fertig implementiert sind.

Hoffe das hilft dir weiter

Ciao, Jörg
 
Das hilft mir auf jeden fall weiter, vielen dank. Aber wo wir schonmal bei abstrakten Klassen sind. Was bringen diese (bzw. die interfaces)? Also warum und wann lohnt es sich diese einzusetzten. Wie diese funktionieren ist mir zwar klar, aber der sinn noch nicht so wirklich.
 
Naja, warum Interfaces in diesem Beispiel sinnvoll sind ist schnell erklärt: egal wer dieses System nutzt und EventListener hinzufügt, die Listener werden immer die selbe API haben. Da der Event Handler nur Objekte akzeptiert, die diese API implementieren, kann der EventHandler sicher sein, dass dieses Objekt bestimmte Methoden besitzt.

Es ist egal, wie die Klasse, die das Interface implementiert, die im Interface definierten Methoden umsetzt. Hauptsache sie sind da ...

Abstrakte Klassen sind noch etwas flexibler. Sie enthalten schon funktionierende Methoden. Daneben gibt es wie in Interfaces auch Methodenrümpfe. Man kann abstrakte Klassen nicht direkt ableiten sondern muss erst eine neue klasse schaffen, die von der abstrakten erbt. Somit ist sichergestellt, dass die neue Klasse bestimmte Methoden fertig implementiert hat.

Das ganze hilft auf jeden Fall, wenn man mit mehereren Leuten zusammenarbeitet oder wenn man ein System hat, das schnell erweiterbar sein soll. Man kann mit diesen Techniken sicherstellen, dass die entsprechenden Entwickler bestimmte Standards einhalten.

Ciao, Jörg
 
Zurück