2009-02-10 118 views
12

我怎样才能做到这一点在PHP如何做一个PHP嵌套类或嵌套方法?

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

我的意思是嵌套的方法或嵌套类(我不知道!) 所以当我打电话的限制方法,用户的孩子就会知道我从“用户”方法(或类)调用它,并且当我调用限制方法 - 或类! - 从评论它也知道这一点。

PHP类能做这件事情的可能结构是什么?


这个问题的原因是因为我对我自己的类数据库工作,所以我可以很容易地使用这样的

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

生成SQL代码“从意见中选择*其中id> 3 limit 10“ 谢谢

+4

这是**链**,不嵌套。 – Pacerier 2015-03-13 13:41:47

回答

17

让方法用所描述的方法返回对象,然后获得你所要的。

所以,只要$DB是一个有comments()-方法的对象,该部分是有效的。如果comments()返回一个具有id()方法的对象,那么该部分也是有效的。然后,id()需要返回一个具有方法limit()的对象。

你的具体情况,你可能想要做这样的事情:

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

在我的例子,每一个方法(此处也未描绘)将返回对象本身,这样的命令可以链接在一起。在完成数据库查询的构建时,实际上通过调用​​来评估查询(在我的情况下)会返回一个表示数据库执行成功的布尔值。

用户nickohm建议将其称为fluent interface。我必须承认这对我来说是一个新词,但是这可能会告诉我更多的知识,而不是术语的用法。 (“我只是写代码,你知道......”

注:$this是一个“神奇”变量指向当前活动的对象。顾名思义,它只是返回自身作为方法的返回值。

+0

很好的例子。我正准备发布完全相同的内容。可能要提到的是,这被称为流畅的界面:http://en.wikipedia.org/wiki/Fluent_interface – nickohrn 2009-02-10 18:07:40

9

标准约定是在每个方法调用结束时返回$ this的实例。所以当返回给调用者时,我们只是引用另一个方法调用。

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

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

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

一个简单的实现方法,让你开始可能会去像:

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

取决于你是否想去复杂,但固体或简单,但不够灵活,你可以实现两个不同的策略。 简单的策略可能会去像这样:

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

或者,但功能更强大:

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

你的想法。无论是重载数据库对象,还是创建一个基本数据库对象和表对象,将大部分智能功能放在表对象中,确保在创建时,表对象存储对数据库对象的引用