Как сделать 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