柔晶美网络工作室

柔晶美网络工作室,倾心于web技术的博客站点

关注我 微信公众号

您现在的位置是: 首页 > 博客日记

通俗举例理解Laravel 中的 Event 和事件

2019-12-25 admin laravel  1613

事件是一种常见的观察者模式的应用。简单的来说,就是当... 干...。这个当... 和干... 在 Laravel 事件中分别对应:
当 (event)... 干 (listener)...

放置 event 和 listener 文件的位置分别是:

app/Events
app/Listeners

用 Artisan 命令可以快速生成一个模板:

php artisan event:generate

下面以用户注册为例,注册方法本来是这样的:

    namespace App\Htt\Controllers;
    use Illuminate\Http\Request;
    class UserController extends Controller
    {
        public function register(Request $request)
        {
            //获取参数
            //验证参数
            //写入数据库
            //return 注册信息
        }
    }

现在有一个需求,要求注册之后给用户的邮箱发一个广告,绝大多数的人(也包括以前的我)就直接在这后面接着写代码了:

    namespace App\Htt\Controllers;
    use Illuminate\Http\Request;
    class UserController extends Controller
    {
        public function register(Request $request)
        {
            //获取参数
            //验证参数
            //写入数据库
            //发送广告邮件
            //return 注册信息
        }
    }

这是比较直观的写法,后来又有需求要发个短信:

    namespace App\Htt\Controllers;
    use Illuminate\Http\Request;
    class UserController extends Controller
    {
        public function register(Request $request)
        {
            //获取参数
            //验证参数
            //写入数据库
            //发送广告邮件
            //发送短信
            //return 注册信息
        }
    }

然后又有需求,要发 IM 消息,这样的需求很多。这些方法如果你封装了,可能也就一行代码。

但是,在实际项目中,这个注册方法里面已经加了很多东西。如果多人开发的话各种不方便。然后想到了 laravel 似乎有这个功能,但是一直都不知道怎么应用,仔细看了一下手册,发现和自己的想法不谋而合。

laravel 的事件功能实际上更倾向是一种管理手段,并不是没了它我们就做不到了,只是它能让我们做得更加好,更加优雅。

laravel 的事件是一种管理 + 实现的体现,它首先有一个总的目录,然后我们可以宏观的看到所有的事件,而不需要每次都要打开控制器的方法我们才能知道注册后会发生什么,这一点很重要,非常的方便,我就不按着 laravel 的顺序来讲,而是按着实际情况来建立这种关系。

现在我们无非就是要在注册之后要做一系列的事情,首先得注册完之后调用一个事件,然后这个事件再做各种各样的事:

    namespace App\Htt\Controllers;
    use Illuminate\Http\Request;
    //我们先引入一个事件类,名字自定义的,之后再一步一步创建
    use App\Events\Register;
    class UserController extends Controller
    {
        public function register(Request $request)
        {
            //获取参数
            //验证参数
            //写入数据库
            //触发事件,以后所有需要注册后要做的事情,都不需要再这里加代码了,我们只需要管理事件就好了
            //event方法是laravel自带方法, $uid是外部参数,看你需要做什么,传什么参数了。注册之后肯定有$uid的嘛
            event(new Register($uid));
            //return 注册信息
        }
    }

找到 \app\Providers\EventServiceProvider.php 文件。给它添加关系,告诉系统,有人用 event () 调用了事件之后要被谁监听得到:

    namespace App\Providers;
    use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
    class EventServiceProvider extends ServiceProvider
    {
        /**
         * The event listener mappings for the application.
         *
         * @var array
         */
        protected $listen = [
            // 用户注册后的事件
            'App\Events\Register' => [
                // 发送广告邮件
                'App\Listeners\SendAdMail',
                // 发送短信
                'App\Listeners\SendSms',
                // 发送帮助信息
                'App\Listeners\SendHelpInformation',
            ],
        ];
    }

这里是注册事件的入口,相当于一个总目录,这样就可以跟注册代码解耦了,以后要加东西我们就不需要再去看注册方法的代码了,现在注册完之后会触发这个 App\Events\Register 类,然后这个类会被 App\Listeners\SendAdMail,App\Listeners\SendSms,App\Listeners\SendHelpInformation 监听得到,我们进入 app\Events 目录,创建 Register 这个类:

    namespace App\Events;
    class Register
    {
        public $uid;
        /**
         * 创建一个新的事件实例.
         *
         * @param  Order  $order
         * @return void
         */
        public function __construct($uid)
        {
            $this->uid = $uid;
        }
    }

这样就可以了。然后去 app\Listeners 目录创建各种要做的事件监听类:

    namespace App\Listeners;
    use App\Events\Register;
    use App\Models\User;
    use Illuminate\Contracts\Queue\ShouldQueue;
    class SendHelpInformation implements ShouldQueue
    {
        public function __construct()
        {
            //
        }
        public function handle(Register $event)
        {
            $uid = $event->uid;
            $user = User::find($uid);
            //......各种实现
        }
    }

这个 handle 方法就是我们要做的具体实现了,有个很方便的功能就是如果 implements ShouldQueue 这个接口的话就会异步队列执行,如果去掉的话就是同步执行。很方便有没有,这样代码就解耦了,不需要再管注册代码了,在这里就能很方便的管理了。多人开发也是单独写自己的 Listeners 就可以了。

文章评论


需要 登录 才能发表评论
热门评论
0条评论

暂时没有评论!