How can I do this in PHP
我怎么能用PHP做到这一点
$myDBClass->users()->limit(5);//output you limited users to 5
$myDBClass->comments()->limit(3);//output you limited comments to 3
what I meant is nested methods or nested class (I don't know!) so when I call the limit method as a child of users it will know that I am calling it from "users" method -or class- and when I call limit method -or class!- from comments It also knows that.
我的意思是嵌套方法或嵌套类(我不知道!)所以当我将limit方法作为用户的子进程调用时,它会知道我从“users”方法调用它 - 或者 - 当我调用时限制方法 - 或类! - 来自评论它也知道。
what is the possible structure for a PHP class to do this thing?
PHP类可以执行此操作的可能结构是什么?
the reason for this question because I am working on my own class for database so I can easily use something like this
这个问题的原因是因为我在自己的数据库类上工作所以我可以很容易地使用这样的东西
$DB->comments()->id(" > 3")->limit(10);
to generate the sql code "select * from comments where id > 3 limit 10" Thanks
生成sql代码“select * from comments where id> 3 limit 10”谢谢
3 个解决方案
#1
17
Have the methods return objects with the methods described, and you get what you are after.
让方法使用所描述的方法返回对象,并获得所需的内容。
So, as long as $DB
is an object that has a comments()
-method, that part is valid. If that comments()
returns an object that has an id()
-method, that part is valid, too. Then, id()
needs to return an object that has the limit()
-method.
因此,只要$ DB是一个具有comments() - 方法的对象,该部分就是有效的。如果comments()返回一个具有id() - 方法的对象,那么该部分也是有效的。然后,id()需要返回一个具有limit() - 方法的对象。
In your particular case, you might want to do something like this:
在您的特定情况下,您可能希望执行以下操作:
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();
In my example, every method (also not depicted here) would return the object itself, so that commands can be chained together. When the construction of the database query is done, you actually evaluate the query by invoking execute()
that (in my case) would return a boolean that would represent the success of the database execution.
在我的示例中,每个方法(此处也未描述)都将返回对象本身,以便命令可以链接在一起。在完成数据库查询的构建时,您实际上通过调用execute()来评估查询(在我的情况下)将返回一个表示数据库执行成功的布尔值。
User nickohm suggested that this is called a fluent interface. I must admit that this is a new term for me, but that tells probably more of my knowledge, than the term's usage. ("I just write code, you know...")
用户nickohm建议将其称为流畅的界面。我必须承认这对我来说是一个新名词,但这可能比我的用法更能说明我的知识。 (“我只是编写代码,你知道......”)
Note: $this
is a 'magic' variable that points to the currently active object. As the name suggests, it just returns itself as the return value for the method.
注意:$ this是一个指向当前活动对象的“魔术”变量。顾名思义,它只返回自己作为方法的返回值。
#2
9
The standard convention for this is to return the instance of $this at the end of each of the method call. So when returned to the caller we are then just referencing another method call.
对此的标准约定是在每个方法调用结束时返回$ this的实例。因此,当返回给调用者时,我们只是引用另一个方法调用。
class Foo
{
public function do_something()
{
return $this;
}
public function do_something_else()
{
return $this;
}
}
$foo->do_something()->do_something_else();
#3
0
A simple to implement method to get you started might go like:
一个简单的实现方法可以让你开始:
class db
{
public function __call($function, $arguments)
{
switch($function) {
// implement table handling here
case 'user':
//do something
return $something;
break;
}
}
}
Depending on whether or not you want to go complicated, but solid or simple, but less flexible you might implement two different strategies. Simple strategy might go like so:
根据您是否想要复杂,但实体或简单,但不太灵活,您可能会实施两种不同的策略。简单的策略可能会这样:
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;
}
}
}
Alternately, but more powerful:
或者,但更强大:
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;
}
}
You get the idea. Either overload the db object, or create a base db object, and table objects, putting much of the intelligence in table objects, ensuring that when created, a table object stores a reference to the db object
你明白了。重载db对象,或创建基本db对象和表对象,将大部分智能放在表对象中,确保在创建时,表对象存储对db对象的引用
#1
17
Have the methods return objects with the methods described, and you get what you are after.
让方法使用所描述的方法返回对象,并获得所需的内容。
So, as long as $DB
is an object that has a comments()
-method, that part is valid. If that comments()
returns an object that has an id()
-method, that part is valid, too. Then, id()
needs to return an object that has the limit()
-method.
因此,只要$ DB是一个具有comments() - 方法的对象,该部分就是有效的。如果comments()返回一个具有id() - 方法的对象,那么该部分也是有效的。然后,id()需要返回一个具有limit() - 方法的对象。
In your particular case, you might want to do something like this:
在您的特定情况下,您可能希望执行以下操作:
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();
In my example, every method (also not depicted here) would return the object itself, so that commands can be chained together. When the construction of the database query is done, you actually evaluate the query by invoking execute()
that (in my case) would return a boolean that would represent the success of the database execution.
在我的示例中,每个方法(此处也未描述)都将返回对象本身,以便命令可以链接在一起。在完成数据库查询的构建时,您实际上通过调用execute()来评估查询(在我的情况下)将返回一个表示数据库执行成功的布尔值。
User nickohm suggested that this is called a fluent interface. I must admit that this is a new term for me, but that tells probably more of my knowledge, than the term's usage. ("I just write code, you know...")
用户nickohm建议将其称为流畅的界面。我必须承认这对我来说是一个新名词,但这可能比我的用法更能说明我的知识。 (“我只是编写代码,你知道......”)
Note: $this
is a 'magic' variable that points to the currently active object. As the name suggests, it just returns itself as the return value for the method.
注意:$ this是一个指向当前活动对象的“魔术”变量。顾名思义,它只返回自己作为方法的返回值。
#2
9
The standard convention for this is to return the instance of $this at the end of each of the method call. So when returned to the caller we are then just referencing another method call.
对此的标准约定是在每个方法调用结束时返回$ this的实例。因此,当返回给调用者时,我们只是引用另一个方法调用。
class Foo
{
public function do_something()
{
return $this;
}
public function do_something_else()
{
return $this;
}
}
$foo->do_something()->do_something_else();
#3
0
A simple to implement method to get you started might go like:
一个简单的实现方法可以让你开始:
class db
{
public function __call($function, $arguments)
{
switch($function) {
// implement table handling here
case 'user':
//do something
return $something;
break;
}
}
}
Depending on whether or not you want to go complicated, but solid or simple, but less flexible you might implement two different strategies. Simple strategy might go like so:
根据您是否想要复杂,但实体或简单,但不太灵活,您可能会实施两种不同的策略。简单的策略可能会这样:
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;
}
}
}
Alternately, but more powerful:
或者,但更强大:
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;
}
}
You get the idea. Either overload the db object, or create a base db object, and table objects, putting much of the intelligence in table objects, ensuring that when created, a table object stores a reference to the db object
你明白了。重载db对象,或创建基本db对象和表对象,将大部分智能放在表对象中,确保在创建时,表对象存储对db对象的引用