16 Stimmen

Wie erstelle ich eine PHP verschachtelte Klasse oder verschachtelte Methoden?

Wie kann ich das in PHP machen?

$myDBClass->users()->limit(5);//Ausgabe: Benutzer auf 5 beschränkt
$myDBClass->comments()->limit(3);//Ausgabe: Kommentare auf 3 beschränkt

Was ich meine, sind verschachtelte Methoden oder verschachtelte Klassen (Ich weiß es nicht!) Also, wenn ich die Limit-Methode als Kind von Benutzern aufrufe, soll sie wissen, dass ich sie aus der "users"-Methode - oder Klasse - aufrufe, und wenn ich die Limit-Methode - oder Klasse! - aus Kommentaren aufrufe, soll sie dies auch wissen.

Was ist die mögliche Struktur für eine PHP-Klasse, um dieses Ding zu tun?


Der Grund für diese Frage ist, dass ich an meiner eigenen Klasse für die Datenbank arbeite, damit ich etwas wie dies leicht verwenden kann

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

um den SQL-Code "select * from comments where id > 3 limit 10" zu generieren Danke

21voto

Henrik Paul Punkte 65301

Die Methoden sollten Objekte mit den beschriebenen Methoden zurückgeben, dann erhalten Sie, was Sie wollen.

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

In Ihrem speziellen Fall möchten Sie vielleicht etwas wie das hier machen:

class DB {
  public function comments() {
    // mach Vorbereitungen, die das Objekt dazu bringen, die "comments"-Tabelle auszuwählen...
    return $this;
  }

  public function id($string) {
    // damit umgehen ...
    return $this;
  }

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

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

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

In meinem Beispiel würde jede Methode (auch hier nicht dargestellt) das Objekt selbst zurückgeben, damit Befehle verkettet werden können. Wenn die Konstruktion der Datenbankabfrage abgeschlossen ist, werten Sie die Abfrage tatsächlich aus, indem Sie execute() aufrufen, das (in meinem Fall) einen boolean-Wert zurückgeben würde, der den Erfolg der Datenbankausführung darstellt.

Benutzer nickohm schlug vor, dass dies eine fluent interface genannt wird. Ich muss zugeben, dass dies ein neuer Begriff für mich ist, aber das sagt wahrscheinlich mehr über mein Wissen aus als über die Verwendung des Begriffs. ("Ich schreibe einfach nur Code, wissen Sie...")

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

10voto

Antonio Haley Punkte 4552

Die Standardkonvention dafür ist, am Ende jedes Methodenaufrufs die Instanz von $this zurückzugeben. Wenn sie an den Aufrufer zurückgegeben wird, verweisen wir dann nur auf einen weiteren Methodenaufruf.

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

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

$foo = new Foo();
$foo->do_something()->do_something_else();

0voto

Mainegreen Punkte 96

Ein einfacher zu implementierender Ansatz, um loszulegen, könnte so aussehen:

class db
{
  public function __call($function, $arguments)
  {
    switch($function) {
      // Implementieren Sie hier die Behandlung von Tabellen
      case 'user':
        // mache etwas
        return $something;
        break;
    }
  }
}

Je nachdem, ob Sie kompliziert, aber solide oder einfach, aber weniger flexibel vorgehen möchten, könnten Sie zwei verschiedene Strategien umsetzen. Eine einfache Strategie könnte so aussehen:

class db
{

  protected $operatingTable;

  public function limit($limitNumber)
  {
    return $this->executeQuery("SELECT * FROM ".$this->operatingTable." LIMIT ".$limitNumber); // wobei executeQuery eine Funktion ist, die eine Abfrage ausführt
  }

  public function __call($function, $arguments)
  {
    switch($function) {
      // Implementieren Sie hier die Behandlung von Tabellen
      case 'user':
        $this->operatingTable='user'; // alternativ, aber weniger sicher: $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); // wobei executeQuery eine Funktion ist, die eine Abfrage ausführt
  }

  public function __call($function, $arguments)
  {
    switch($function) {
      // Implementieren Sie hier die Behandlung von Tabellen
      case 'user':
        $user = new user($this); // übergeben Sie die Datenbank an das Objekt, damit das Tabellenobjekt eine Referenz zur Datenbank haben kann
        return $user;
        break;
    }
  }
}

class baseTableClass
{
  protected $db; // eine Instanz der Klasse db

  function limit($limitNumber)
  {
    $db->execute($aStatementDerivedFromThisClassesInformation); // führen Sie ein SQL-Kommando aus, basierend auf Informationen über die Tabelle in der Klasse
  }

}

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

Sie verstehen das Prinzip. Überlasten Sie entweder das db-Objekt oder erstellen Sie ein Basis-Db-Objekt und Tabellenobjekte, indem Sie einen Großteil der Intelligenz in Tabellenobjekten platzieren, und stellen sicher, dass beim Erstellen ein Tabellenobjekt eine Referenz zum db-Objekt speichert

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X