__call

Die Verwendung von __call($methodName, $parameters) bietet sich beispielsweise an, um ein generisches Stellvertreter-Objekt (siehe „Stellvertreter“) zu implementieren, das anstelle eines anderen Objektes verwendet werden kann. So implementiert die Klasse Cache (Beispiel 2.6) einen Mechanismus für das Vorhalten von bereits berechneten Ergebnissen von Methoden beliebiger anderer Klassen.

Beispiel 2.6: Die Klasse Cache

<?php
class Cache {
  protected $cache = array();
  protected $object;
 
  public function __construct($object) {
    $this->object = $object;
  }
 
  public function __call($methodName, $parameters) {
    $id = md5($methodName . serialize($parameters));
 
    if (!isset($this->cache[$id])) {
        try {
            $class  = new ReflectionClass($this->object);
            $method = $class->getMethod($methodName);
 
            $this->cache[$id] = $method->invoke(
              $this->object,
              $parameters[0],
              $parameters[1]
            );
        }
 
        catch (ReflectionException $e) {
        }
    }
 
    return $this->cache[$id];
  }
}
?>


Die Generizität wird durch Verwendung der Reflection API („Die Reflection API“) erreicht. Der Interzeptor nutzt diese, um beim Aufruf einer von der Klasse Cache nicht selbst zur Verfügung gestellten Methode zu testen, ob das aggregierte Objekt $object die geforderte Methode besitzt.

Beispiel 2.7: Die Klasse Rechner

<?php
class Rechner {
  public function rechne($a, $b) {
    print "Rechner::rechne($a$b) ausgeführt.\n";
 
    return $a * $b;
  }
}
?>


Beispiel 2.8 zeigt die Verwendung der Klasse Cache am Beispiel eines Rechner-Objektes (Beispiel 2.7).

Beispiel 2.8: Verwendung der Klassen Cache und Rechner

<?php
require_once 'Cache.php';
require_once 'Rechner.php';
 
$rechner = new Cache(new Rechner);
$rechner->rechne(23, 42);
$rechner->rechne(23, 42);
?>
Rechner::rechne(23, 42) ausgeführt.