Laravel 如何實現既能靜態呼叫,又能動態呼叫

tiroGuang發表於2018-12-04

首先要知道類當中方法訪問控制。

  • public 公開的,可以被繼承,也可以被外部訪問。
  • protected 可以被繼承,但是不可以被外部訪問。
  • private 不可以被繼承,也不能被外部訪問。

在laravel中,有一些方法不管是靜態呼叫,還是動態呼叫,都能夠使用。這都要歸功於php的__callStatic__call魔術方法以及laravel作者的設計。

class Model
{
    protected function increment($column, $amount = 1, array $extra = [])
    {
        return $this->incrementOrDecrement($column, $amount, $extra, 'increment');
    }

    public function __call($method, $parameters)
    {
        if (in_array($method, ['increment', 'decrement'])) {
            return $this->$method(...$parameters);
        }

        return $this->forwardCallTo($this->newQuery(), $method, $parameters);
    }

    public static function __callStatic($method, $parameters)
    {
        return (new static)->$method(...$parameters);
    }
}

舉個例子,比如說有一個使用者表,裡面有一個年齡欄位,我們想要讓年齡能夠自增,於是我們有兩種寫法

  • (new User)->increment('age');
  • User::increment('age');

首先看第一種,因為我們User繼承了Model類,但是increment方法前有個protected導致我們無法從外部訪問這個方法。但是不用慌張,這個時候__call魔術方法就起到了效果,他會幫我們去訪問increment方法。

第二種,我們用靜態呼叫increment方法,執行的時候,程式就去找有沒有定義的靜態increment方法,找了一圈沒有找到,怎麼辦?這個時候__callStatic開始發揮作用。我們用的是User類,因為延遲靜態繫結的緣故,可以看成:

return (new User)->increment('age');

是不是回到了第一種寫法的樣子。

基礎真滴很重要!!!

不積跬步無以至千里

相關文章