Laravel Model 利用 Macroable 為資料模型新增宏能力

ThinkSNS發表於2017-08-22
【摘要】簡單的說一下宏能力,這個類是 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; 

拿到使用者釋出的所有問題了。

以上程式碼都來自於 Plus,看完整的開發程式碼可以看倉庫

GitHub: (開源不易,求 Star )

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31448874/viewspace-2143938/,如需轉載,請註明出處,否則將追究法律責任。

相關文章