Как сделать PHP вложенный класс или вложенные методы?

Как это сделать в PHP

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

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

Какова возможная структура для PHP-класса для выполнения этой задачи?


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

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

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

Ответ 1

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

Итак, до тех пор, пока $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();

В моем примере каждый метод (также не изображенный здесь) вернет сам объект, так что команды могут быть соединены вместе. Когда выполняется построение запроса к базе данных, вы фактически оцениваете запрос, вызывая execute(), который (в моем случае) вернет логическое значение, которое будет представлять успех выполнения базы данных.

Пользователь nickohm предположил, что это называется свободным интерфейсом . Я должен признать, что это новый термин для меня, но это говорит, вероятно, больше о моих знаниях, чем о термине использования. ( "Я просто пишу код, вы знаете..." )

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

Ответ 2

Стандартное соглашение для этого - вернуть экземпляр $this в конце каждого вызова метода. Поэтому, когда мы возвращаемся к вызывающему абоненту, мы просто ссылаемся на вызов другого метода.

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

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

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

Ответ 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