【问题标题】:How to do a PHP nested class or nested methods?如何做一个 PHP 嵌套类或嵌套方法?
【发布时间】:2010-10-06 17:10:49
【问题描述】:

我如何在 PHP 中做到这一点

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

我的意思是嵌套方法或嵌套类(我不知道!) 因此,当我将 limit 方法作为 users 的子级调用时,它会知道我是从“users”方法 - 或类 - 调用它,而当我从 cmets 调用 limit 方法 - 或类! - 它也知道这一点。

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


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

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

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

【问题讨论】:

  • 老兄,这是链接,而不是嵌套。

标签: php design-patterns fluent-interface


【解决方案1】:

对此的标准约定是在每个方法调用结束时返回 $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】:

    让这些方法返回具有所描述方法的对象,然后你就会得到你想要的。

    所以,只要$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 是一个指向当前活动对象的“魔法”变量。顾名思义,它只是将自身作为方法的返回值返回。

    【讨论】:

    【解决方案3】:

    一个简单的实现方法可以帮助您入门:

    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 对象的引用

    【讨论】:

      猜你喜欢
      • 2017-07-29
      • 2017-05-25
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-01
      相关资源
      最近更新 更多