[英]Dynamically generate PHP static methods to instantiate new object
我正在嘗試構建一個允許方法鏈接查詢它的數據庫類。 我想通過將第一個調用設為靜態來像 Laravel 的 Eloquent 一樣實例化它。
看這個例子:
class Database
{
public function construct($data) {
$this->data = $data;
}
public function filter($criteria) {
// ...
return $this;
}
public static function filter($data, $criteria) {
$obj = new Database($data);
$obj->filter($criteria);
return $obj;
}
public function add($value) {
// ...
return $this;
}
public static function add($data, $value,) {
$obj = new Database($data);
$obj->add($value);
return $obj;
}
}
例如,這將允許我:
Database::add($myData, $newValue)->add($anotherValue)->filter('isString');
Database::filter($myData, 'isNumber')->add($thirdValue);
這不應該是真實的,但我很好奇是否有辦法減少我的靜態方法中的重復代碼或完全刪除它們。 我想到了魔術方法__callStatic()
但我不確定它是否是實現它的最佳方法。
如果知道的人可以向我解釋一下大型框架如何處理此類任務,我將不勝感激。
是的,它確實是通過魔術方法__callStatic()
完成的。
在這里,您有 Laravel Eloquent 代碼片段,這些來自Model類,還有更多事情要做,但這些與您的案例相關:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters); // delegating to __call method
}
public function __call($method, $parameters)
{
...
// self explanatory
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
}
// newQuery method lead to this method:
public function newModelQuery()
{
return $this->newEloquentBuilder(
$this->newBaseQueryBuilder() // deals with getting database connection
)->setModel($this);
}
// newEloquentBuilder return Builder class which have the "where" etc. methods defined.
在您的情況下,簡單示例:
class Database
{
protected static $connection;
protected $query; // could be array or better object
public function __construct() {
if(!static::$connection){
static::$connection = new mysqli(...); // for example
}
}
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
// in case $query is object have these two methods defined there
// also delegate with __call method to the query object
public function filter($criteria) {
... // filling $query variable
return $this;
}
public function add($value) {
... // filling $query variable
return $this;
}
public function fetch_assoc() {
$stmt = static::$connection->prepare(...);
... // fill the prepared statements with $query data
return $stmt->get_result()->fetch_assoc();
}
}
您可以使用對象的靜態方法,但不能在該方法中使用 $this。
您不能定義具有相同名稱的靜態和非靜態方法。
在大多數情況下,我只需要非靜態方法,並且在極少數情況下,我沒有為該方法調用而實例化的對象實例 - 並調用非靜態方法。
在極少數情況下,我也會使用不同的名稱定義靜態方法,例如 filterStatic()。 這是一種非常罕見的情況,在這種情況下,非靜態方法包裝了靜態方法以避免代碼重復。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.