如何做PHP嵌套类或嵌套方法?

时间:2009-02-10 18:00:41

标签: php design-patterns fluent-interface

我如何在PHP中执行此操作

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

我的意思是嵌套方法或嵌套类(我不知道!) 因此当我将limit方法作为用户的子进程调用时,它将知道我从“users”方法 - 或类 - 以及当我调用limit方法 - 或类! - 来自注释它时也知道它。

PHP类可能的结构是什么?


这个问题的原因是因为我正在为自己的数据库工作,所以我可以轻松地使用这样的东西

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

生成sql代码“select * from comments where id> 3 limit 10” 感谢

3 个答案:

答案 0 :(得分: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();
$DB->comments()->id(" > 3")->limit(10);

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

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

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

答案 1 :(得分:10)

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

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

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

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

答案 2 :(得分: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;
  }
}

你明白了。重载db对象,或创建基本db对象和表对象,将大部分智能放在表对象中,确保在创建时,表对象存储对db对象的引用