思考并回答以下问题:
- 在某些操作的节点,比如解析后,插入必要的一些操作。怎么理解?
- 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扩展中触发了。)