使用事件

Yii的时间提供了一个简单的实现, 它允许你监听订阅发生在你web应用中各种各样的事件。例如,你也许希望发送一个通知:每次当你发布一个新材料时,将这个新文档通知到你的订阅者。

准备

  1. 按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的应用。
  2. 在你的服务器上执行如下SQL代码,创建文章表:
  1. CREATE TABLE 'article' (
  2. 'id' int(11) NOT NULL AUTO_INCREMENT,
  3. 'name' varchar(255) DEFAULT NULL,
  4. 'description' text,
  5. PRIMARY KEY ('id')
  6. ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8;
  1. 使用Gii生成Article模型。
  2. 使用./yii服务命令运行你的web服务器。

如何做…

  1. 添加一个测试action到\controllers\SiteController:
  1. <?php
  2. public function actionTest()
  3. {
  4. $article = new Article();
  5. $article->name = 'Valentine\'s Day\'s coming? Aw crap! I forgot to get a girlfriend again!';
  6. $article->description = 'Bender is angry at Fry for dating a robot. Stay away from our women. You\'ve got metal fever, boy. Metal fever';
  7. // $event is an object of yii\base\Event or a child class
  8. $article->on(ActiveRecord::EVENT_AFTER_INSERT,
  9. function($event) {
  10. $followers = ['john2@teleworm.us',
  11. 'shivawhite@cuvox.de', 'kate@dayrep.com' ];
  12. foreach($followers as $follower) {
  13. Yii::$app->mailer->compose()
  14. ->setFrom('techblog@teleworm.us')
  15. ->setTo($follower)
  16. ->setSubject($event->sender->name)
  17. ->setTextBody($event->sender->description)
  18. ->send();
  19. }
  20. echo 'Emails has been sent';
  21. });
  22. if (!$article->save()) {
  23. echo VarDumper::dumpAsString($article->getErrors());
  24. };
  25. }
  1. 使用如下代码更新config/web.php控件mailer:
  1. 'mailer' => [
  2. 'class' => 'yii\swiftmailer\Mailer',
  3. 'useFileTransport' => false,
  4. ],
  1. 在你的浏览器中访问如下网址:

http://localhost:8080/index.php?r=site/test.

  1. 另外检查http://www.fakemailgenerator.com/inbox/teleworm.us/john2/

使用事件 - 图1

工作原理…

我们已经创建了一个Article模型,并在Article模型中为ActiveRecord::EVENT_AFTER_INSERT事件添加了一个handler。它意味着我们每次保存一个新文章,这个事件都会被触发,然后我们的handler就会被调用。

在现实世界中,我们也许希望在我们每次发布一个新文章时,通知我们的博客订阅者。在一个实际应用中,我们将会有一个follower或者user表,and with different blog sections not only single blog。在这个例子中,在保存好我们的模型以后,我们通知了我们的订阅者john2@teleworm.usshivawhite@cuvox.dekate@dayrep.com。在上一步中,我们只是证明了用户已经收到了我们的通知,特别是john2。你可以用任意名称创建你自己的事件,这里我们使用了一个内置的事件,叫做ActiveRecord::EVENT_AFTER_INSERT,它会在每次插入到数据库中调用。

例如,我们可以创建我们自己的事件。只需要使用如下代码添加一个新的actionTestNew:

  1. <?php
  2. public function actionTestNew()
  3. {
  4. $article = new Article();
  5. $article->name = 'Valentine\'s Day\'s coming? Aw crap! I forgot to get a girlfriend again!';
  6. $article->description = 'Bender is angry at Fry for dating a robot. Stay away from our women. You\'ve got metal fever, boy. Metal fever';
  7. // $event is an object of yii\base\Event or a child class
  8. $article->on(Article::EVENT_OUR_CUSTOM_EVENT, function($event) {
  9. $followers = ['john2@teleworm.us', 'shivawhite@cuvox.de',
  10. 'kate@dayrep.com' ];
  11. foreach($followers as $follower) {
  12. Yii::$app->mailer->compose()
  13. ->setFrom('techblog@teleworm.us')
  14. ->setTo($follower)
  15. ->setSubject($event->sender->name)
  16. ->setTextBody($event->sender->description)
  17. ->send();
  18. }
  19. echo 'Emails have been sent';
  20. });
  21. if ($article->save()) {
  22. $article->trigger(Article::EVENT_OUR_CUSTOM_EVENT);
  23. }
  24. }

同时按照如下方式将EVENT_OUR_CUSTOM_EVENT常量加入到模型models/Article中:

  1. class Article extends \yii\db\ActiveRecord
  2. {
  3. CONST EVENT_OUR_CUSTOM_EVENT = 'eventOurCustomEvent';
  4. }

访问http://localhost:8080/index.php?r=site/test-new。

你应该看到相同的结果,并且所有给订阅者的通知会再发一遍。主要的区别是我们使用了自定义的事件名。

保存以后,我们触发了我们的事件。事件是通过调用yii\base\Component::trigger()触发的。这个方法需要一个事件名称,以及一个可选的事件对象,它描述了传递给事件handler的参数。

参考

欲了解更多信息参见http://www.yiiframework.com/doc-2.0/guide-conceptevents.
html