最近做项目正好用到了“事件”这个东西,所以就研究了一下(事件有很多种方式,我这里只介绍最常见的一种)
1.在 app/Providers/EventServiceProvider 里的 $listen[]写"App\Events\TestEvent'=>['App\Listeners\TestEventListener'],"
2.执行 php artisan event:generate
3.这时会在 Events 和 Listeners 目录下生成对应的TestEvent和TestEventListener文件(PS:Events和Listeners框架默认没有,执行了命令就会有的 )
4.到这里,事件所需的文件都已经创建好了。TestEventListener的handle()方法就是事件触发后所执行的方法,也就是说,事件出发后,所执行的动作(业务逻辑)都写到这个方法里,而且你会看到 参数是TestEvent的实例,也就是说,TestEvent里的public属性的东西,你都可以在这里用。
5.就是怎么触发事件呢?很简单,在你需要触发的地方写 event(new TestEvent())就可以了,就会触发事件,自动去执行handle()里的方法了。到这里基本就结束了。但是有时候我们想从外部传一些数据给handle()里的业务逻辑用,怎么办呢?修改TestEvent()构造函数:
class TestEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $p;//注意,一定是public的
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($arg)
{
$this->$p = $arg;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
这样在 event(new TestEvent())要写成 event(new TestEvent(‘我是穿过来的字符串’))。因为TestEventListener 的handle(TestEvent $event)参数是 TestEvent实例,所以我们可以用$event->p 来拿到传过来的参数。到此,事件就全部结束了
这里我想吐槽一下laravel的设计,大部分还是很优雅的,但是事件这块真的不咋地,比较冗余吧,还是很混乱:
1.名字起的不好,event 和 Listeners(事件和监听器)这个名字就不好,监听器是啥?很懵逼啊!其实监听器就是“事件发生后,要执行的动作!”,,我觉得还不如叫 event 和 eventHandle 的好 或者 event 和 eventAction
2.有点儿冗余,为啥非得用俩呢 event 和 Listeners ,无形中增加学习难带,直接在event里写“出发事件后执行的动作”不就好了,非得跑到Listeners里面的handle($event)去写(也可能是php原因,做不到这一点)。
3.实现 事件 的方式太多种了,这是好事儿也是坏事,这样很多初学者很懵逼,一上来眼花缭乱,不知道该用哪一种!本人还是比较喜欢python的思想“做一件事情,只用一种方法”。
4.还有一点是,laravel的事件和我们常说的 click之类的事件不是一回事儿的。简单的说,click事件是用户来触发的,什么时候触发,哪个按钮触发都不确定,反正就是用户来触发,我们绑定好要执行的代码就好了。但是laravel的事件不是的这么用的,它的初衷其实为了代码解耦用的,事件的触发是我们说了算的,就是你在哪里调用 event(new TestEvent()),哪里就会触发事件!(当然这块还要跟数据库那几个 creating created updating updated saving saved事件区分开,这里就不做过多解释了,有兴趣自己研究吧)