Magische Methoden und Interzeptoren mit PHP


F18 High Contrast
Attribution-NonCommercial-NoDerivs License by SkipSteuart
In PHP gibt es sogennante magische Methoden. Diese werden nicht explizit aufgerufen, sondern werden vom Interpreter in gewissen Situationen ausgeführt. Dazu gehören Konstruktor, Dekonstruktor. Die Implementierung magischer Methoden ist optional. Die Interzeptoren sind eine Untermenge der magischen Methoden. Mit diesen Methoden kann man bequem Execeptions oder Laufzeitfehler im objekt-orientierten Umfeld abfangen.

Beginnen möchte ich mir der Funktion __toString(), die beim Debuggen sehr nützlich ist. Dazu ein kleines Beispiel:

class Post{
	private $title ="", $text = "";


	public function __construct($title="", $text=""){
		$this->title =  $title;
		$this->text=$text;
	}
}
$post = new Post("mein 1. Eintrag",  "Schönes Wetter, spazieren gegangen, Eis gegessen.");
echo $post;

Der Befehl echo post liefert einen Fehler. Wenn man ein Objekt in PHP genauer betrachten möchte, muß man dies mit print_r() oder var_dump() tun – oder mit __toString():

	public function __toString(){
		ob_start();
		var_dump($this);
		$retval=ob_get_clean();
		return $retval;
	}

Da __toString() eine Zeichenkette zurückgibt, kann man alle String Funktionen von PHP anwenden:

class Post{
	private $title ="", $text = "";


	public function __construct($title="", $text=""){
		$this->title =  $title;
		$this->text=$text;
	}

	public function __toString(){
		return "

{$this->title}

{$this->text}"; } } $post = new Post("mein 1. Eintrag", "Schönes Wetter, spazieren gegangen, Eis gegessen."); echo str_replace("ö", "ö", $post);

Mit __set() und __get() kann man Zugriffe auf nicht gesetzte oder geschützte Attribute abfangen.

class Post{
        /**....**/
        public $foo="bar";
	public function __get($attrib){
		echo "$attrib gibts nicht, oder du hast keinen zugriff darauf!

"; } } $post = new Post("mein 1. Eintrag", "viel passiert heute."); echo $post->bla; echo $post->title; echo $post->foo;

Die Rückgabe sieht dann so aus:

bla gibts nicht, oder du hast keinen zugriff darauf!
title gibts nicht, oder du hast keinen zugriff darauf!

bar

Der Zugriff auf nicht definierte oder geschützte Methoden läßt sich mit __call abfangen:

class Post{
	public function __call($meth, $args){
		echo "Die Methode $meth gibts nicht, oder du hast keinen Zugriff darauf!

"; if (!empty($args)){ echo "Parameter:
"; foreach ($args as $arg) echo "$arg
"; } } } $post->leaveComment("karl heinz", "echt super", "karl@heinz.de");

Die Ausgabe sieht dann so aus:

Die Methode leaveComment gibts nicht, oder du hast keinen Zugriff darauf!
Parameter:
karl heinz
echt super
karl@heinz.de

Die beiden Interzeptoren __isset() und __unset() können entsprechende Anfragen an das Objekt abfangen:

class Post{
	public function __isset($value){
		return isset($this->$value);
	}
	public function __unset($value){
		if(isset($this->$value))
			unset ($this->$value);
	}

}
$post = new Post();
echo isset($post->title);
unset ($post->title);

Statt nur Fehler mit den Interzeptoren auszuwerfen, kann man Klassen schreiben, die zwar ein wenig „dirty“ sind aber auch funktionieren:

class DirtyPost{
	public  $attributes = array();

	public function __construct($title="", $text=""){
		$this->attributes['title'] =  $title;
		$this->attributes['text'] =  $text;

	}

	public function __toString(){
		$retval ="

{$this->attributes['title']}

"; $retval .=$this->attributes['text']; $retval .=$this->getComments(); return $retval; } public function __get($attrib){ if (isset($this->attributes[$attrib])) return $this->attributes[$attrib]; } public function __set($attrib, $value){ $this->attributes[$attrib] = $value; } public function __call($meth, $args){ switch ($meth){ case 'addComment': array_push ($this->attributes, $args); break; default: echo "$meth gibt es nicht."; case 'getComments': $retval =""; foreach ($this->attributes as $attrib){ if(is_array($attrib)){ $retval.= "Kommentar:
"; foreach ($attrib as $a) $retval.= $a.'

'; } }//each return $retval; break; }//switch }//__call } $post = new DirtyPost(); $post->title="Mein 1. Eintrag

"; $post->text = "Heute wars nicht so schoen

"; $post->addComment('Hans', 'hans@hansi.de', 'das schert mich nicht :)'); $post->addComment('Ingo', 'ingo@web.de', 'Morgen wirds besser'); echo $post;

Ausgabe:

Mein 1. Eintrag

Heute wars nicht so schoen
Kommentar:
Hans

hans@hansi.de

das schert mich nicht :)

Kommentar:
Ingo

ingo@web.de

Morgen wirds besser

Ausgelassen habe ich __callstatic mit dem man Aufrufe von nicht existierenden statischen Methoden abfangen kann.
Mit den Interzeptoren kann man sich viel Arbeit sparen, aber auch viel Verwirrung stiften. Das letzte Beispiel funktioniert zwar (wenn man serialize() und unserialize() noch einbindet, hat man einen minimalistischen Blog) allerdings leiden Lesbarkeit, Wiederverwendbarkeit darunter.

Advertisements
Dieser Beitrag wurde unter php abgelegt und mit , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s