# Hook
Hook 本身是钩子的意思,在程序中是一种简化的Event的事件机制,这些“钩子”会埋在特定代码中,标示钩子所在的位置。当代码执行到该Hook时,触发对应的 Hook Function 并按顺序执行,如果没有任何对应的 Hook Function ,则不不会改变任何事情。
Hook 目前有两种,分别是”Action“及”Filter“,Action和Filter的使用方法是一样的,但是用处略有不同,Action一般用于某些动作,Action永远不会返回任何东西,而Filter用于处理数据,总是返回对某个数据处理后的数据
# Action Hook 动作处理
编写中
# Filter Hook 数据处理
Filter 类型的Hook主要是用来处理数据,在程序运行中,你可以针对Hook的数据进行改变,这样的好处是可以解除程序耦合,比如定义了一个数组,如果希望在别的地方能改变它,而不是直接修改这个数组,那么我们就可以使用Filter
Filter Hook 提供了两个方法来处理数据,分别是:用于触发钩子的Filter::fire() 和 用于监听钩子的Filter::listen()
添加一个Filter钩子,你只需要在用到在需要处理数据的地方触发这个钩子,如我们有一个数据‘Hello Filter’需要处理:
~~~
$hello = Filter::fire('hook.hello', 'Hello Filter');
~~~
如果没有添加任何对这个filter的监听处理,那么$hello值依然是 ‘Hello Filter’,但是如果我们添加了一个Filter监听:
~~~
Filter::listen('hook.hello', function ($value) {
$value = '你好,Filter';
return $value;
});
~~~
此时$hello 的值将变成 ‘你好,Filter’
如果我们在别的地方有另外一个对‘hook.hello’的监听
~~~
Filter::listen('hook.hello', function ($value) {
// 这时的$value已经不再是'Hello Filter',而是上一个监听器返回的数据 ‘你好,Filter’
$value = $value . '=== :)';
return $value;
});
~~~
此时$hello 的值将变成 ‘你好,Filter=== :)’
fire的第一个参数是钩子名称,第二个参数是等待hook的数据,他将依次参入下一个监听中进行处理,当然我们也可以拥有更多参数,但是第三、第四甚至更多的参数只能用来辅助处理第二个参数
listen的第一个参数同样是钩子名称,第二个参数是闭包函数或者类的方法(MyNamespace\Listen@myListen),第三个参数是优先级,如果不定义优先级,那么优先级默认为20
~~~
$value = Filter::fire('hook.second', $param, $argument1);
// 此时 $value 为 $param
~~~
~~~
// 添加第一个闭包监听
Filter::listen('hook.second', function ($param, $argument1) {
$param = $param + $argument1
return $param;
});
// 此时 $value 为 $param + $argument1
~~~
~~~
// 再添加一个类方法监听
Filter::listen('hook.second', MyNamespace\Listen@myListen);
//MyNamespace\Listen中
public function myListen ($param, $argument1)
{
// 此时传入的$param已经变成了上一次监听返回的结果 ($param + $argument1)
$param = $param + $argument1*2
return $param;
}
// 此时 $value 为 ($param + $argument1) + $argument1*2
~~~
举个实际例子:在系统后台的头部我们有个主导航条,我们希望你能在自己的模块或者其它地方扩展它,所以我们定义了一个名称为 **global.navbar** 的Filter触发器,用来扩展导航(默认并没有任何导航,所以传入的待处理导航数据是空数组)
`Filter::fire('global.start',[])`
在Core模块的start.php中,我们对该Filter进行监听处理
~~~
\Filter::listen('global.navbar', function($navbar){
// 主页
$navbar['core.index'] = [
'text' => trans('core::master.index'),
'href' => route('admin.index'),
'class' => 'index',
'active' => Route::is('admin.index')
];
return $navbar;
},1);
~~~
这时候我们就成功添加了一个导航,在Site模块的start.php中,我们继续对该Filter进行监听处理
~~~
\Filter::listen('global.navbar',function($navbar){
// 站点名称
$navbar['core.sitename'] = [
'text' => config('site.name'),
'href' => route('site.config.base'),
'class' => 'sitename',
'active' => Route::is('site.*')
];
return $navbar;
},0);
~~~
这时候我们又添加了一个导航到主导航中,在实际的导航展示中,代码如下:
~~~
@foreach(Filter::fire('global.navbar',[]) as $navbar)
<li class="item {{$navbar['class'] or ''}} {{$navbar['active'] ? 'active' : ''}}">
<a href="{{$navbar['href']}}">{{$navbar['text']}}</a>
</li>
@endforeach
~~~
这时候我们实际上展示出来是hook进来的两个导航项