簡單的說一下巨集能力,這個類是 Illuminate\Support\Traits\Macroable
其中利用過載實現了可以定義巨集的功能,通俗一點江,就是通過 macro 靜態方法新增回撥,並定義一個名字,利用 __call
噹噹前類沒有這個函式的時候執行這個函式名註冊的回撥。
產生需求
在使用 Laravel 開發 ThinkSNS Plus 的時候,因為很多功能塊都沒有寫在一個庫裡面,利用 擴充包 的形式新增實際功能,裡面很多地方也用到了 “多型多對多” 的關係,問題來了,我開發一個問答程式,想要給使用者模型增加發布的問題或者回答的關係,起初是繼承一份 User
模型,新增了關係,之後就發現問題了,因為使用者的 tag 是使用多型多對多的關係,我通過繼承的使用者模型是無法拿到這種關係資料的因為 ***able_type
是 user 資料模型類名稱或者別名。而我繼承之後類也就發生改變了。
完成需求
隨之想到,在 Laravel 中有一個 Trait 叫做 Macroable
然後發現 Builder
都有這種能力,而 Model 沒有,隨之也將這個 Trait 新增到要使用的model上,後來發現,如果其他模型也要用是不是也要再新增一次?隨之寫了一份 Trait :
trait Macroable
{
use \Illuminate\Support\Traits\Macroable {
__call as macroCall;
}
/**
* Get a relationship value from a method.
*
* @param string $key
* @return mixed
* @author Seven Du <shiweidu@outlook.com>
*/
public function getRelationValue($key)
{
$relation = parent::getRelationValue($key);
if (! $relation && static::hasMacro($key)) {
return $this->getRelationshipFromMethod($key);
}
return $relation;
}
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
* @author Seven Du <shiweidu@outlook.com>
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return $this->macroCall($method, $parameters);
}
return parent::__call($method, $parameters);
}
/**
* Handle dynamic static method calls into the method.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
return parent::__callStatic($method, $parameters);
}
}
只要在要使用的 model 中 use 即可。
使用
有了這個 Trait 那麼我們新增到 User
模型中,就可以使用巨集能力為其動態新增函式了:
User::macro('questions', function () {
return $this->hasMany(Question::class, 'user_id', 'id');
});
這樣,我們可以直接 :
$questions = $user->questions;
拿到使用者釋出的所有問題了。
開源不易,https://github.com/slimkit/thinksns-plus 求 star。
Seven 的程式碼太渣,歡迎關注我的新擴充包 medz/cors 解決 PHP 專案程式設定跨域需求。