思考并回答以下问题:
- 在某些操作的节点,比如解析后,插入必要的一些操作。怎么理解?
- call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] ) : mixed;
- app()->rebinding(‘money’, Closure);是这样使用吗?
简介
回调函数在容器中,用的也很多。先说作用,在某些操作的节点,比如解析后,插入必要的一些操作。感觉就像hook和事件Event一样。
在Container中,有好几种callbacks:1
2
3
4
5protected $reboundCallbacks = []; // 所有注册的回调
protected $globalResolvingCallbacks = []; // 所有全局解析回调
protected $globalAfterResolvingCallbacks = []; // 所有全局解析之后回调
protected $resolvingCallbacks = []; // 所有类的解析回调
protected $afterResolvingCallbacks = []; // 所有类的解析之后回调
他们分别出现在不一样的地方被调用。
我们以第一个rebound举例,其他几个大同小异。
实测例子
在extend之前rebinding一个回调函数,当extend完成,会输出this is rebinding callbacks1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34class Money
{
public function getAmount(){
return 100;
}
}
class Dollar extends Money
{
public function getAmount()
{
return 1;
}
}
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);
}
}
源码
触发rebound()回调函数的源码如下:
1 | /** |
1.解析当前的对象。
2.然后查看当前容器中是否存在对应的rebound回调函数,如果有,遍历所有对应的回调函数,使用call_user_func执行回调函数。
2.1 看下getReboundCallbacks,获取对应所有的回调函数,是通过reboundCallbacks数组获得。源码如下:
1 | /** |
3.最后这个rebound()方法我们上一章1.2中知道,它会在extend绑定完成后会调用触发。
回调函数的绑定
我们上面涉及了调用,我们下面看下如何绑定。
回调函数的绑定是通过函数rebinding处理的,很简单,就是把对应的回调函数存入reboundCallbacks数组。
最后一句,如果这个对象已经绑定过了,还会贴心的返回这个对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
* Bind a new callback to an abstract's rebind event.
*
* @param string $abstract
* @param \Closure $callback
* @return mixed
*/
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扩展中触发了。)