有时候当我们单纯的看 Laravel手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多加思考会发现有时候这些服务其实我们一直都见过。下面就事件、事件监听举一个很简单的例子你就会发现。
这个例子是关于文章的浏览数的实现,当用户查看文章的时候文章的浏览数会增加1,用户查看文章就是一个事件,有了事件,就需要一个事件监听器,对监听的事件发生后执行相应的操作(文章浏览数加1),其实这种监听机制在 Laravel 中是通过观察者模式实现的.
链接
laravel 事件监听使用大概分为以下步骤:
- ① 注册事件和事件监听器
- ② 生成事件文件和事件监听器文件
- ③ 定义事件
- ④ 定义事件监听器
- ⑤ 分发事件 (调用事件)
1. 注册事件和事件监听器
在我们使用事件之前,首先应该先去 app/Providers/ 目录下打开 EventServiceProvider.php 文件之后我们会看到如下的一个数组
-
protected $listen = [
-
'App\Events\Event' => [
-
'App\Listeners\EventListener',
-
],
-
'App\Events\ArticleEvent' => [
-
'App\Listeners\ArticleEventListener',
-
],
-
'App\Events\AdminLoginEvent' => [
-
'App\Listeners\AdminLoginEventListener',
-
],
-
'Illuminate\Database\Events\QueryExecuted' => [
-
'App\Listeners\QueryListener'
-
],
-
];
数组 $listen 是用来注册我们的事件和事件监听器的一个数组,其中数组的键为我们需要定义的事件,值对应的为我们需要定义的事件监听器,
比如我这里,需要注册的
事件为:ArticleEvent 指定路径为 App\Events\ArticleEvent (处理文章点击的一个事件)
事件监听器为:ArticleEventListener 指定路径为 App\Listeners\ArticleEventListener (监听文章点击事件的监听器)
我们需要把指定路径对应上图,增加到数组中,
此时我们已经注册好了事件和监听器
2. 生成事件文件和事件监听器文件
事件文件存放在 app/Events 目录下 监听器 存放在 app/Listeners 目录下 此时我们虽然定义好了监听器,但是对应文件并不存在,我们需要使用 laravel 的 artisan 命令 来在指定目录下生成 事件文件 ArticleEvent 和 事件监听 ArticleEventListener 文件
php artisan event:generate
文件生成之后,下面开始定义事件
3. 定义事件
打开 app/Events 目录下的 ArticleEvent .php 事件文件,如下有个结构函数
-
class ArticleEvent
-
{
-
use
Dispatchable,
InteractsWithSockets,
SerializesModels;
-
public $article;
-
/**
-
* Create a new event instance.
-
*
-
* @return void
-
*/
-
public
function __construct(Article $article)
-
{
-
//
-
$this->article = $article;
-
}
-
-
/**
-
* Get the channels the event should broadcast on.
-
*
-
* @return \Illuminate\Broadcasting\Channel|array
-
*/
-
public
function broadcastOn()
-
{
-
return
new PrivateChannel(
'channel-name');
-
}
-
}
当我们在调用事件的时候我们有时候需要,给事件传递参数,这个参数可能是个 ORM 模型 也可能是个数据集 或者是个字符串,此时如果我们希望事件能够接收到我们传递的参数,就需要在 construct () 结构函数中来 定义接收,有两种方法:
第一种
我们使用依赖注入的方式定义接收的参数 (文档中便是此方法), 假如我们接收的参数为 Eloquent ORM 对象 Article 则我们需要在事件中 引入 Article模型,然后在 construct () 指定依赖,在定义完接收对象之后,还需要定义一个 pubic 属性 然后将接收的参数赋值给这个 public 属性,以便于 事件监听 程序调用 我们这里定义为 public $article 如下:
-
namespace
App\
Events;
-
-
use
App\
Http\
Models\
Article;
-
public
function __construct(Article $article)
-
{
-
//
-
$this->article = $article;
-
}
第二种
使用普通的参数接收方式,直接在 construct () 函数中指定一个参数用来接收调用事件传递的参数,这种就和我们正常函数传参相同,同样我们需要定义一个 公有属性,将参数赋值给这个公有属性,这里仍然使用 public $article,如下
-
public
function __construct($article)
-
{
-
//
-
$this->article = $article;
-
}
以上我们,可以通过两种方式来定义事件的接收
4. 定义事件监听器
打开 app/Listeners 目录下的 ArticleEventListener.php 事件文件,在事件监听文件中有个 handle 函数用来处理我们的业务逻辑
如下:
-
public
function handle(ArticleEvent $event)
-
{
-
//
-
$id = $event->article->id;
-
Article::where(
'id',$id)->increment(
'hits');
-
}
5. 分发事件 (调用事件)
上面我们都定义好之后在我们业务需要的地方执行分发事件 (调用事件) 使用 event (new 事件名 (参数)) 来执行事件分发 (事件调用)
注意: 如果我们定义事件的时候使用的是依赖注入的方式来传递参数,那么我们在分发事件的时候 只能传递我们指定的依赖,否则会报错,例如我们上面使用的 Article $article 依赖 则在调用事件的时候 我们只能在我们的控制器中 传递 模型 Article的 ORM 模型如下:
-
use App\
Events\ArticleEvent;
-
use App\
Http\Models\Article;
-
public
function article_detail(Request $request)
-
{
-
$article_id = Input::get(
'article_id');
-
$info = Article::where([
'id'=>$article_id])->first();
-
event(
new ArticleEvent($info));
-
-
return view(
'home.article.article_detail')->with([
-
'info'=>$info
-
]);
-
}
当我们查看文章时,文章点击数就会自动加1
当我们使用第二种方法来定义事件的接收时,我们在调用事件时,传递的参数就会没有限制了 我们可以根据需要传递不同的参数到事件中去,然后在事件监听中 根据业务需求来获取参数处理业务逻辑
以上便是两种定义方式的,两种事件调用方式