__call() zur Erweiterung von Factory-Klassen nutzen

Wenn eine vorhandene Klasse erweitert werden soll, kann sie einfach vererben und die neue Klasse instanziieren.
Anders sieht es bei Factory-Klassen aus, die je nach Parameter ein anderes Objekt zurückgeben (z. B. für eine Datenbank-Klasse).
Hier müsste man dann schon in jede der Klassen die neue Funktion einfügen, um sie auch in jedem Objekt verfügbar zu haben.

Die PHP5-Funktion __call() kann hier einiges an Arbeit abnehmen. Sie fängt Aufrufe von Methoden ab, die in der Klasse selbst nicht implementiert sind und nimmt dabei zwei Parameter entgegen: den Namen der Methode und ein Array von Parametern, die an die Methode übergeben werden sollen.

Wenn man ein System wie Pear::DB oder ADOdb nutzt, wird eine Erweiterung (z. B. eine Funktion insert($table, $values)) recht schwierig. Meist hat man hier eine Factory-Funktion oder -Klasse, die jeweils unterschiedliche Objekte zurückgeben.
Mit __call() kann man (in PHP5) die entsprechende Methode in der Factory-Klasse einbauen und alle anderen Methoden (sofern existent) an die aktuelle Klasse weiterleiten.

Ein Beispiel mit ADOdb:

Die original Factory-Klasse

static function getInstance()
{
    static $instance = false;
    if (!$instance || !is_a($instance, 'ADOConnection') {
        $instance = newADOConnection('mysql');
        $instance->connect('localhost', 'user', 'geheim', 'datenbank');
     }
     return $instance;
}

Damit wird je nach Datenbank-Typ ein anderes Objekt zurückgegeben, aber die Erweiterung müsste in allen Klassen vorgenommen werden.

Ein Ansatz mit __call()

class DB
{
    protected $conn = null;
    public function __construct()
    {
        $this->conn = newADOConnection('mysql');
        $this->conn->connect('localhost', 'user', 'geheim', 'datenbank');
    }
    //Die neue Funktion
    public function insert($table, $values)
    {
         $table = trim($table); //eventuell noch überprüfen        
         $sql = "INSERT INTO `$table`;
         $sql .= ''; //mache hier irgendwas mit den Werten
         return $this->conn->execute($sql);
     }
     //Hier werden alle anderen Methoden an $this->conn weitergeleitet
    public function __call($method, $params)
    {
        if (method_exists($this->conn, $method) {
            return call_user_func_array(array($this->conn, $method), $params);
        } else {
            //Gebe Fehler aus
        }
     }
}

Ähnliche Artikel

Geschrieben am
Share |
Dein Kommentar:

Sämtliche Html-Tags werden gelöscht, der Kommentar kann mit Textile formatiert werden.
Vor dem Absenden müsst ihr euch einmal die Vorschau ansehen.