Как сделать PHP вложенный класс или вложенные методы? - PullRequest
12 голосов
/ 10 февраля 2009

Как я могу сделать это в PHP

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

я имел в виду вложенные методы или вложенный класс (я не знаю!) поэтому, когда я вызываю метод limit как дочерний элемент пользователей, он узнает, что я вызываю его из метода «users» -или class- и когда я вызываю метод limit -or class!

Какова возможная структура для класса PHP, чтобы сделать это?


причина этого вопроса, потому что я работаю над своим собственным классом для базы данных, поэтому я могу легко использовать что-то вроде этого

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

для генерации кода sql "выберите * из комментариев, где id> 3 limit 10" Спасибо

Ответы [ 3 ]

17 голосов
/ 10 февраля 2009

Пусть методы возвращают объекты описанными методами, и вы получите то, что вам нужно.

Таким образом, пока $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 предположил, что это называется свободный интерфейс . Я должен признать, что это новый термин для меня, но это говорит, вероятно, больше о моих знаниях, чем использование термина. ( «Я просто пишу код, вы знаете ...» )

Примечание: $this - это «магическая» переменная, которая указывает на текущий активный объект. Как следует из названия, оно просто возвращает себя в качестве возвращаемого значения для метода.

10 голосов
/ 10 февраля 2009

Стандартное соглашение для этого - возвращать экземпляр $ 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();
0 голосов
/ 10 февраля 2009

Простой в реализации метод для начала работы может выглядеть так:

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

...