2009-02-10 28 views
12

Come posso fare questo in PHPCome eseguire una classe nidificata PHP o metodi nidificati?

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

quello che volevo dire è metodi nidificati o classe annidata (non so!) in modo che quando chiamo il metodo limite come un bambino di utenti si saprà che Lo chiamo dal metodo "users" -o classe- e quando chiamo metodo limite -o classe! - dai commenti Lo sa anche questo.

qual è la struttura possibile per una classe PHP per fare questa cosa?


la ragione di questa domanda perché sto lavorando su mia classe per il database in modo da poter usare facilmente qualcosa di simile

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

per generare il codice SQL "select * from commenti dove id> 3 limite 10 " Grazie

+4

Amico, questo è ** concatenamento **, non annidato. – Pacerier

risposta

17

I metodi restituiscono gli oggetti con i metodi descritti e ottieni ciò che cerchi.

Quindi, finché $DB è un oggetto che ha un metodo comments(), quella parte è valida. Se quello comments() restituisce un oggetto che ha un metodo id(), anche quella parte è valida. Quindi, id() deve restituire un oggetto che ha il metodo limit().

Nel vostro caso particolare, si potrebbe desiderare di fare qualcosa di simile:

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

Nel mio esempio, ogni metodo (anche non rappresentata qui) sarebbe tornato l'oggetto stesso, in modo che i comandi possono essere concatenati . Una volta completata la costruzione della query del database, la query viene effettivamente valutata invocando execute() che (nel mio caso) restituirebbe un valore booleano che rappresenterebbe il successo dell'esecuzione del database.

L'utente nickohm ha suggerito che questo è chiamato fluent interface. Devo ammettere che questo è un termine nuovo per me, ma che dice probabilmente più delle mie conoscenze, che l'uso del termine. ("Ho appena scrivere il codice, lo sai ...")

Nota:$this è una variabile 'magia' che punta all'oggetto attualmente attivo. Come suggerisce il nome, si restituisce solo come valore di ritorno per il metodo.

+0

Ottimo esempio. Stavo per pubblicare qualcosa esattamente uguale. Potrebbe voler dire che questa si chiama interfaccia fluente: http://en.wikipedia.org/wiki/Fluent_interface – nickohrn

+0

Questo è usato in ExtPHP http://nexus.zteo.com/2008/03/04/extphp-an- ExtJS-converterwrapper-per-php-sviluppatori / – Seiti

9

La convenzione standard per questo è restituire l'istanza di $ questo alla fine di ciascuna chiamata al metodo. Quindi, quando torniamo al chiamante, facciamo semplicemente riferimento a un'altra chiamata al metodo.

0

Una semplice da implementare il metodo per iniziare potrebbe andare come:

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

A seconda se si desidera o meno andare complicato, ma solido o semplice, ma meno flessibile si potrebbe implementare due diverse strategie. semplice strategia potrebbe andare in questo modo:

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

In alternativa, ma più potente:

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

Si ottiene l'idea. O sovraccarichi l'oggetto db, o crei un oggetto db di base, e oggetti tabella, mettendo molta intelligenza negli oggetti tabella, assicurando che quando viene creato, un oggetto tabella memorizzi un riferimento all'oggetto db