Comment faire une classe imbriquée en PHP ou des méthodes imbriquées?

Comment puis-je faire cela en PHP

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

ce que je voulais dire c'est méthodes imbriquées ou classe imbriquée (Je ne sais pas!) ainsi, quand j'appelle la méthode limit en tant qu'enfant d'utilisateurs, il saura que je l'appelle de la méthode "users"- ou classe - et quand j'appelle la méthode limit-ou classe!- d'après les commentaires Il sait aussi que les.

Quelle est la structure possible pour QU'une classe PHP fasse cette chose?


la raison pour cette question parce que je travaille sur ma propre classe pour la base de données de sorte que je peux facilement utiliser quelque chose comme ça

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

pour générer le code sql" sélectionner * dans les commentaires où id > 3 limite 10" Merci

12
demandé sur David Grant 2009-02-10 21:00:41

3 réponses

demandez aux méthodes de retourner les objets avec les méthodes décrites, et vous obtenez ce que vous recherchez.

ainsi, tant que $DB est un objet qui a une méthode comments() , cette partie est valide. Si cette comments() renvoie un objet qui a une méthode id() , cette partie est également valide. Ensuite, id() doit retourner un objet qui a la méthode limit() .

dans votre cas particulier, vous pourriez vouloir faire quelque chose comme ceci:

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();

dans mon exemple, chaque méthode (aussi pas représenté ici) retournerait l'objet lui-même, de sorte que les commandes puissent être enchaînées ensemble. Lorsque la construction de la requête de base de données est fait, vous évaluez réellement la requête en invoquant execute() qui (dans mon cas) retournerait un booléen qui représenterait le succès de l'exécution de la base de données.

nickohm utilisateur suggéré que ce est appelé une interface fluent . Je dois admettre que c'est un nouveau terme pour moi, mais qui dit probablement plus de mes connaissances, que l'usage du terme. ( "je viens d'écrire du code, vous le savez..." )

Note: $this est une variable "magique" qui pointe vers l'objet actuellement actif. Comme le nom l'indique, il retourne simplement lui-même comme valeur de retour pour la méthode.

17
répondu Henrik Paul 2009-02-10 18:13:00

la convention standard pour ceci est de retourner l'instance de $this à la fin de chaque appel de méthode. Donc, une fois retournés à l'appelant, nous faisons simplement référence à un autre appel de méthode.

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

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

$foo->do_something()->do_something_else();
9
répondu Antonio Haley 2009-02-10 18:04:45

une méthode simple pour mettre en œuvre pour vous lancer pourrait aller comme:

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

selon que vous voulez ou non aller compliqué, mais solide ou simple, mais moins flexible, vous pourriez mettre en œuvre deux stratégies différentes. Une stratégie Simple pourrait être ainsi:

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;
    }
  }
}

alternativement, mais plus puissant:

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;
  }
}

vous comprenez. Soit surcharger l'objet db, soit créer un objet base db, et une table objets, mettant une grande partie de l'intelligence dans les objets de table, en s'assurant que lors de la création, un objet de table stocke une référence à l'objet db

0
répondu Mainegreen 2009-02-10 18:33:15