问题描述
我该如何在php
中执行此操作$myDBClass->users()->limit(5);//output you limited users to 5 $myDBClass->comments()->limit(3);//output you limited comments to 3
我的意思是嵌套方法或嵌套类(我不知道!) 因此,当我从用户的孩子中调用限制方法时,它将知道我正在从"用户"方法或类调用它,而当我调用限制方法 - 或class! - 从评论中也知道.
PHP类做这件事的可能结构是什么?
出于这个问题的原因,因为我正在为数据库工作,因此我可以轻松地使用此类内容
$DB->comments()->id(" > 3")->limit(10);
生成SQL代码"从注释中选择 * ID> 3限制10" 谢谢
推荐答案
使方法返回对象,并获得了所描述的方法.
因此,只要$DB是一个具有comments() -Method的对象,该部分是有效的.如果该comments()返回具有id() -Method的对象,则该部分也是有效的.然后,id()需要返回一个具有limit() -Method的对象.
在您的特殊情况下,您可能想做这样的事情:
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是指向当前活动对象的"魔术"变量.顾名思义,它只是作为方法的返回值返回.
其他推荐答案
标准约定是在每个方法调用的末尾返回$的实例.因此,当返回呼叫者时,我们只是引用另一个方法调用.
class Foo { public function do_something() { return $this; } public function do_something_else() { return $this; } } $foo = new Foo(); $foo->do_something()->do_something_else();
其他推荐答案
一种易于实现的方法来使您开始使用:
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对象的引用
问题描述
How can I do this in 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.
what is the possible structure for a PHP class to do this thing?
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
推荐答案
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.
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(); $DB->comments()->id(" > 3")->limit(10);
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.
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...")
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.
其他推荐答案
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.
class Foo { public function do_something() { return $this; } public function do_something_else() { return $this; } } $foo = new Foo(); $foo->do_something()->do_something_else();
其他推荐答案
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