1.3 - Laravel 5.6 - Callbacks 回撥函式機制

HarveyNorman發表於2020-03-04

回撥函式在容器中,用的也很多。先說作用,在某些操作的節點,比如解析後,插入必要的一些操作。感覺就像hook和事件Event一樣。

在container中,有好幾種callbacks

protected $reboundCallbacks = [];//所有註冊的回撥
protected $globalResolvingCallbacks = [];//所有全域性解析回撥
protected $globalAfterResolvingCallbacks = [];//所有全域性解析之後回撥
protected $resolvingCallbacks = [];//所有類的解析回撥
protected $afterResolvingCallbacks = [];//所有類的解析之後回撥

他們分別出現在不一樣的地方被呼叫。

我們以第一個rebound舉例: 其他幾個大同小異。

觸發rebound()回撥函式的原始碼如下:

1.解析當前的物件

2.然後檢視當前容器中是否存在對應的rebound回撥函式,如果有,遍歷所有對應的回撥函式,使用call_user_func執行回撥函式。


protected function rebound($abstract)
{
    $instance = $this->make($abstract);
    foreach ($this->getReboundCallbacks($abstract) as $callback) {
        call_user_func($callback, $this, $instance);
    }
}

2.1看下getReboundCallbacks,獲取對應所有的回撥函式是通過reboundCallbacks陣列獲得。原始碼如下:


protected function getReboundCallbacks($abstract)
{
    if (isset($this->reboundCallbacks[$abstract])) {
        return $this->reboundCallbacks[$abstract];
    }
    return [];
}

3.最後這個rebound()方法我們上一章1.2中知道,它會在extend繫結完成後會呼叫觸發。

回撥函式的繫結

我們上面涉及了呼叫,我們下面看下如何繫結。

回撥函式的繫結是通過函式rebinding處理的,很簡單,就是把對應的回撥函式存入reboundCallbacks陣列。

最後一句,如果這個物件已經繫結過了,還會貼心的返回這個物件。

public function rebinding($abstract, Closure $callback)
{
    $this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
    if ($this->bound($abstract)) {
        return $this->make($abstract);
    }
}

總結

回撥函式也很簡單,我們只要知道在這個例子中,他通過方法rebinding,把回撥函式儲存在陣列reboundCallbacks中,然後使用rebound以及其他幾個函式在不同的地方觸發。(extend擴充套件中觸發了。)

實測例子

在extend之前rebinding一個回撥函式,當extend完成,會輸出this is rebinding callbacks

class ExampleTest extends TestCase
{
    public function testClosure()
    {
        app()->bind('money', Money::class);
        app()->rebinding('money', function(){
            var_dump("this is rebinding callbacks");
        });

        app()->extend('money',function(){
            return new Dollar();
        });

        $boss= app()->make('money');
        $output = $boss->getAmount();
        $this->assertEquals($output, 1);
    }
}

//

class Money
{
    public function getAmount(){
        return 100;
    }
}

class Dollar extends Money
{
    public function getAmount()
    {
        return 1;
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章