回撥函式在容器中,用的也很多。先說作用,在某些操作的節點,比如解析後,插入必要的一些操作。感覺就像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 協議》,轉載必須註明作者和本文連結