2009-02-10 8 views
12

Wie kann ich dies in PHP tunWie werden eine PHP-geschachtelte Klasse oder verschachtelte Methoden ausgeführt?

$myDBClass->users()->limit(5);//output you limited users to 5 
$myDBClass->comments()->limit(3);//output you limited comments to 3 

, was bedeutete, dass ich ist verschachtelte Methoden oder verschachtelte Klasse (ich weiß es nicht!) so, wenn ich die Grenze Methode als Kind der Nutzer anrufen soll es wissen, Ich rufe es von "Benutzer" -Methode -oder Klasse- und wenn ich Limit-Methode -oder Klasse aufrufen- aus Kommentaren, weiß es auch.

was ist die mögliche Struktur für eine PHP-Klasse, diese Sache zu tun?


der Grund für diese Frage, weil ich auf meine eigenen Klasse für Datenbank arbeitete, so kann ich einfach so etwas wie diese

 $DB->comments()->id(" > 3")->limit(10); 

verwenden, um den SQL-Code „select * from Kommentare where id> zu erzeugen, 3 limit 10 " Danke

+4

Dude this is ** Verkettung speichert **, nicht nisten. – Pacerier

Antwort

17

Lassen Sie die Methoden Objekte mit den beschriebenen Methoden zurückgeben, und Sie erhalten, was Sie suchen.

Also, solange $DB ein Objekt ist, das eine comments() -Methode hat, ist dieser Teil gültig. Wenn das comments() ein Objekt zurückgibt, das eine -Methode hat, ist dieser Teil ebenfalls gültig. Dann muss ein Objekt zurückgeben, das die limit() -Methode hat.

In Ihrem speziellen Fall, könnte man so etwas tun:

class DB { 
    public function comments() { 
    // do preparations that make the object select the "comments"-table... 
    return $this; 
    } 

    public function id($string) { 
    // handle this too... 
    return $this; 
    } 

    public function limit($int) { 
    // also this 
    return $this; 
    } 

    public function execute() { 
    $success = try_to_execute_accumulated_db_commands(); 
    return $success; 
    } 
} 

$DB = new DB(); 

In meinem Beispiel jede Methode würde (auch hier nicht dargestellten) Rück das Objekt selbst, so dass Befehle miteinander verkettet werden können . Wenn die Konstruktion der Datenbankabfrage abgeschlossen ist, werten Sie die Abfrage tatsächlich aus, indem Sie execute() aufrufen, die (in meinem Fall) einen booleschen Wert zurückgeben würde, der den Erfolg der Datenbankausführung darstellen würde.

Benutzer nickohm vorgeschlagen, dass dies eine fluent interface genannt wird. Ich muss zugeben, dass dies ein neuer Begriff für mich ist, aber das sagt wahrscheinlich mehr von meinem Wissen, als die Verwendung des Begriffs. ("I-Code nur schreiben, wissen Sie ...")

Hinweis:$this ist eine 'magische' Variable, die auf das aktive Objekt zeigt. Wie der Name schon sagt, gibt es nur selbst als Rückgabewert für die Methode zurück.

+0

Großartiges Beispiel. Ich wollte gerade etwas genau das gleiche machen. Vielleicht möchte ich erwähnen, dass dies eine fließende Schnittstelle genannt wird: http://en.wikipedia.org/wiki/Fluent_interface – nickohrn

+0

Dies wird in ExtPHP verwendet http://nexus.zteo.com/2008/03/04/extphp-an- extjs-converterwrapper-für-php-entwickler / – Seiti

9

Die Standardkonvention dafür ist die Rückgabe der Instanz von $ this am Ende jedes Methodenaufrufs. Wenn wir also zum Aufrufer zurückkehren, verweisen wir nur auf einen anderen Methodenaufruf.

class Foo 
{ 
    public function do_something() 
    { 
    return $this; 
    } 

public function do_something_else() 
{ 
    return $this; 
    } 
} 

$foo->do_something()->do_something_else(); 
0

Eine einfache Methode implementieren Sie gehen könnte wie zu erhalten begonnen:

class db 
{ 
    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     //do something 
     return $something; 
     break; 
    } 
    } 
} 

Je nachdem, ob Sie nicht wollen, gehen kompliziert, aber feste oder einfach, aber weniger flexibel Sie könnten implementieren zwei verschiedene Strategien. Einfache Strategie könnte wie so gehen:

class db 
{ 

    protected $operatingTable; 

    public function limit($limitNumber) 
    { 
    return $this->executeQuery("SELECT * FROM ".$this->operatingTable." LIMIT ".$limitNumber); // where executeQuery is a function that runs a query 
    } 

    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     $this->operatingTable='user'; // alternately, but less secure: $this->operatingTable=$function; 
     return $this; 
     break; 
    } 
    } 
} 

Alternativ, aber leistungsstärker:

class db 
{ 
    protected $operatingTable; 

    public function limit($limitNumber) 
    { 
    return $this->executeQuery("SELECT * FROM ".$this->operatingTable." LIMIT ".$limitNumber); // where executeQuery is a function that runs a query 
    } 

    public function __call($function, $arguments) 
    { 
    switch($function) { 
     // implement table handling here 
     case 'user': 
     $user = new user($this); // pass in the database to the object, so the table object can have a reference to the db 
     return $user; 
     break; 
    } 
    } 
} 

class baseTableClass 
{ 
    protected $db; // an instance of class db 

    function limit($limitNumber) 
    { 
    $db->execute($aStatementDerivedFromThisClassesInformation); // execute a sql command, based on information about the table in the class 
    } 

} 

class user extends baseTableClass 
{ 
    public function __construct($db) { 
    $this->db = $db; 
    } 
} 

Sie bekommen die Idee. Überladen Sie entweder das DB-Objekt oder erstellen Sie ein Basis-DB-Objekt und Tabellenobjekte, indem Sie einen Großteil der Intelligenz in Tabellenobjekte legen und sicherstellen, dass ein Tabellenobjekt einen Verweis auf das DB-Objekt

Verwandte Themen