yii2 event实例(基于restful风格)

本案例参考 http://www.yiichina.com/topic/6690 而来, 感谢作者的贡献

需求:有这么一个场景:

一个屋子里面,有一个人,有一只猫、一只老鼠、一条狗, 猫叫了以后老鼠跑了,狗看见了猫,猫也跑了,人看见了把鞋子丢了过去。这么一个场景如何用restful风格的YII2的事件机制来表示呢?

分析:

猫叫的动作触发了老鼠跑的动作,同时也触发了狗看的动作,而狗看到了猫以后,触发了猫跑这个动作,看到发出的动静,人把鞋子扔了出去

猫的叫声触发了一系列动作

现在把这个场景具体化:
* 猫叫了(当插入一条数据成功后,说明猫叫成功了), 触发了老鼠跑(插入一条数据),同时触发了狗看(插入一条数据)

* 而狗看(插入一条数据成功后,说明狗看猫成功了)到了猫以后,触发了猫跑(再次插入一条数据)这个动作,
* 看到发出的动静(老鼠跑:插入一条数据成功后,说明人看到),人把鞋子扔了出去(插入一条数据)

数据表如下:
注意: 该sql适用于mysql数据库

create table test_house_event (

     `id` int unsigned not null primary key auto_increment, 

        `type` tinyint unsigned not null comment '类型:1 猫, 2 老鼠, 3 狗, 4 人', 

        `content` varchar (100) not null comment '动作内容', 

    `createdAt` int unsigned not null, 

) engine=innodb auto_increment=1 default charset=utf8 collate=utf8_general_ci comment='test_house_event';

上代码:
首先,前端发起一条请求, 创建一条'猫叫了'的数据记录, 用来触发相应的事件:

// 前端请求部分
$data = [

'content' => date('Y-m-d H:i:s') . '我是一只猫, 我叫唤了一声: 喵~'
];
$uri = xxx . '/devTestEvent/testEvent/house';  // 请求uri
$.post($uri, $data, function() {
    // 返回响应的数据, 进行处理
})

php部分:

1.Controller:

HouseController.php:

<?php
/**
*需求:有这么一个场景:
*一个屋子里面,有一个人,有一只猫、一只老鼠、一条狗
*猫叫了以后老鼠跑了,狗看见了猫,猫也跑了,人看见了把鞋子丢了过去。
*这么一个场景如何用YII2的事件机制来表示呢?
*分析:
*猫叫的动作触发了老鼠跑的动作,同时也触发了狗看的动作
*而狗看到了猫以后,触发了猫跑这个动作
*看到发出的动静,人把鞋子扔了出去
*
*猫的叫声触发了一系列动作
*
*现在把这个场景具体化:
*猫叫了(当插入一条数据成功后,说明猫叫成功了), 触发了老鼠跑(插入一条数据),同时触发了狗看(插入一条数据)
*而狗看(插入一条数据成功后,说明狗看猫成功了)到了猫以后,触发了猫跑(再次插入一条数据)这个动作,
*看到发出的动静(老鼠跑:插入一条数据成功后,说明人看到),人把鞋子扔了出去(插入一条数据)
*/

namespace webserver\controllers\devTestEvent\testEvent;

use common\models\devTestEvent\testEvent\BaseModel;
use yii\rest\ActiveController
use webserver\models\devTestEvent\testEvent\Cat;

class HouseController extends ActiveController
{

public $modelClass = Cat::class;

public function actionIndex()
{
    return BaseModel::find()->asArray()->all();
}
}

2.Model:

BaseModel.php
<?php
/**
* testEvent BaseModel:基础Model,该案例所有Model都继承该类
*/
namespace common\models\devTestEvent\testEvent;

use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;

/**
* Class BaseModel
* @package common\models\devTestEvent\testEvent
*/
class BaseModel extends ActiveRecord
{

/**
 * 类型: 猫
 */
public const TYPE_CAT = 1;

/**
 * 类型: 老鼠
 */
public const TYPE_MOUSE = 2;
/**
 * 类型: 狗
 */
public const TYPE_DOG = 3;
/**
 * 类型: 人
 */
public const TYPE_PERSON = 4;

/**
 * 数据表名
 * @inheritdoc
 */
public static function tableName()
{
    return 'test_house_event';
}

/**
 * 校验规则
 * @inheritdoc
 */
public function rules()
{
    return [
        ['type', 'required'],
        ['type', 'in', 'range' => [self::TYPE_CAT, self::TYPE_MOUSE, self::TYPE_DOG, self::TYPE_PERSON]],
        [['content'], 'string'],
        [['content'], 'trim'],
    ];
}

/**
 * 开启事务处理机制
 * @inheritdoc
 */
public function transactions()
{
    return [
        self::SCENARIO_DEFAULT => self::OP_ALL,
    ];
}

public function behaviors()
{
    return [
        [
            'class' => TimestampBehavior::class,
            'createdAtAttribute' => 'createdAt',
            'updatedAtAttribute' => false,
        ],
    ];
}

}
Cat.php 

<?php

namespace webserver\models\devTestEvent\testEvent;

use common\models\devTestEvent\testEvent\BaseModel;
use webserver\exceptions\Exception;
use webserver\event\devTestEvent\testEvent\CatEvent;
use webserver\event\devTestEvent\testEvent\DogEvent;

/**
* Class Cat
*
* @property int $id
* @property int $type
* @property string $content
* @property int $createdAt
*
* @package webserver\models\devTestEvent\testEvent
*/
class Cat extends BaseModel
{

/**
 * event: 猫叫了
 */
public const EVENT_CAT_SHOUT = 'shout';

/**
 * 是否绑定自定义事件: is Binding User Defined Event
 * @var bool
 */
public $isBindingUDE = true;

public function init()
{
    parent::init();
    $this->type = self::TYPE_CAT;  // `type`默认值为猫
}

/**
 * 事件handler: 狗看了一眼猫后的事件处理器
 * @param DogEvent $event
 * @throws EzException
 */
public function run(DogEvent $event)
{
    $model = new self();
    $model->content = date('Y-m-d H:i:s') . "我是那只猫,刚才叫了一声, 结果那只狗(#{$event->dogId})看了我一眼,所以我跑了";
    $model->isBindingUDE = false;  // 该属性会在save之前和save之后使用,目的: 多次save时判断是否绑定事件, 只有猫叫了才会绑定和触发一系列事件,猫的其他动作不会绑定和触发事件
    $result = $model->save();
    if (!$result) {
        // 该处可自定义Exception
        throw new Exception(Exception::ERROR_TRANSACTION_ERROR, '跑慢了, 被狗逮着了, 喵~');
    }
}

public function beforeSave($insert)
{
    if ($this->isBindingUDE) {
        // 猫叫了(当插入一条数据成功后,说明猫叫成功了), 触发了老鼠跑(插入一条数据),同时触发了狗看(插入一条数据)
        $this->on(self::EVENT_CAT_SHOUT, [Mouse::class, 'run']);
        $this->on(self::EVENT_CAT_SHOUT, [Dog::class, 'look']);
    }

    return parent::beforeSave($insert);
}

public function afterSave($insert, $changedAttributes)
{
    parent::afterSave($insert, $changedAttributes);
    if ($insert && $this->isBindingUDE) {
        // 插入一条数据成功(猫叫成功了)后, 并且绑定了自定义事件, 触发事件
        $catEvent = new CatEvent();
        $catEvent->catId = $this->id;
        $this->trigger(self::EVENT_CAT_SHOUT, $catEvent);
    }
}
}

Mouse.php:

<?php

/**

* Mouse Model

*/

namespace webserver\models\devTestEvent\testEvent;

use common\models\devTestEvent\testEvent\BaseModel;
use webserver\exceptions\Exception;
use webserver\event\devTestEvent\testEvent\CatEvent;
use webserver\event\devTestEvent\testEvent\MouseEvent;

/**
* Class Mouse
*
* @property int $id
* @property int $type
* @property string $content
* @property int $createdAt
*
* @package webserver\models\devTestEvent\testEvent
*/
class Mouse extends BaseModel
{

/**
 * event: 老鼠听到了猫叫, 跑了
 */
public const EVENT_MOUSE_RUN = 'run';

public function init()
{
    parent::init();
    $this->type = self::TYPE_MOUSE;  //`type`默认为老鼠
}

/**
 * 事件handler: 猫叫了之后,触发老鼠跑的事件处理器
 * @param CatEvent $event
 * @throws EzException
 */
public function run(CatEvent $event)
{
    $model = new self();
    $model->content = date('Y-m-d H:i:s') . "我是一只老鼠, 听到了猫(#{$event->catId})叫, 所以我逃跑了!";
    $result = $model->save();
    if (!$result) {
        throw new Exception(Exception::ERROR_TRANSACTION_ERROR, '地上打滑,逃跑失败,被猫抓住了');
    }
}

public function beforeSave($insert)
{
    // 看到老鼠发出的动静(老鼠成功逃跑:插入一条数据成功后,说明老鼠成功逃跑了),于是人把鞋子扔了出去(插入一条数据)
    $this->on(self::EVENT_MOUSE_RUN, [Person::class, 'do']);

    return parent::beforeSave($insert);
}

public function afterSave($insert, $changedAttributes)
{
    parent::afterSave($insert, $changedAttributes);
    if ($insert) {
        $mouseEvent = new MouseEvent();
        $mouseEvent->mouseId = $this->id;
        $this->trigger(self::EVENT_MOUSE_RUN, $mouseEvent);
    }
}
}

Dog.php: 

<?php
/**
* Dog Model
*/

namespace webserver\models\devTestEvent\testEvent;

use common\models\devTestEvent\testEvent\BaseModel;
use webserver\exceptions\Exception;
use webserver\event\devTestEvent\testEvent\CatEvent;
use webserver\event\devTestEvent\testEvent\DogEvent;

/**
* Class Dog
*
* @property int $id
* @property int $type
* @property string $content
* @property int $createdAt
*
* @package webserver\models\devTestEvent\testEvent
*/
class Dog extends BaseModel
{

/**
 * event: 狗听到猫叫,看了一眼
 */
public const EVENT_DOG_LOOK = 'look';

public function init()
{
    parent::init();
    $this->type = self::TYPE_DOG;  // `type`默认为狗
}

/**
 * 事件handler: 猫叫了之后,狗看的事件处理器
 * @param CatEvent $event
 * @throws EzException
 */
public function look(CatEvent $event)
{
    $model = new self();
    $model->content = date('Y-m-d H:i:s') . "我是一只狗, 听到猫(#{$event->catId})叫, 所以看了猫一眼";
    $result = $model->save();
    if (!$result) {
        throw new Exception(Exception::ERROR_TRANSACTION_ERROR, '呃,没睡醒,看花了眼');
    }
}

public function beforeSave($insert)
{
    // 狗看(插入一条数据成功后,说明狗看猫成功了)到了猫以后,触发了猫跑(再次插入一条数据)这个动作
    $this->on(self::EVENT_DOG_LOOK, [Cat::class, 'run']);

    return parent::beforeSave($insert);
}

public function afterSave($insert, $changedAttributes)
{
    parent::afterSave($insert, $changedAttributes);
    if ($insert) {
        $dogEvent = new DogEvent();
        $dogEvent->dogId = $this->id;
        $this->trigger(self::EVENT_DOG_LOOK, $dogEvent);
    }
}
}

Person.php: 

<?php
/**
* Person Model
*/

namespace webserver\models\devTestEvent\testEvent;

use common\models\devTestEvent\testEvent\BaseModel;
use ezsoft\exceptions\EzException;
use webserver\event\devTestEvent\testEvent\MouseEvent;

/**
* Class Person
*
* @property int $id
* @property int $type
* @property string $content
* @property int $createdAt
*
* @package webserver\models\devTestEvent\testEvent
*/
class Person extends BaseModel
{

public function init()
{
    parent::init();
    $this->type = self::TYPE_PERSON;
}

/**
 * 事件handler: 老鼠跑发出的动作热看到后的事件处理器
 * @param MouseEvent $event
 * @throws EzException
 */
public function do(MouseEvent $event)
{
    $model = new self();
    $model->content = date('Y-m-d H:i:s') . "我是这屋子的主人, 看到有一只老鼠(#{$event->mouseId})在跑,我把鞋子扔了出去";
    $result = $model->save();
    if (!$result) {
        throw new EzException(EzException::ERROR_TRANSACTION_ERROR, '鞋子没扔出去, 上面有胶水,粘在手上了');
    }
}
}

3.XxxEvent部分:该部分会在trigger事件时使用

CatEvent.php:

<?php

/**

* 该Event 封装了与事件相关的有关数据,并提供一些功能函数作为辅助.

*/

namespace webserver\event\devTestEvent\testEvent;

use yii\base\Event;

/**
* Class CatEvent
* @package webserver\event\devTestEvent\testEvent
*/
class CatEvent extends Event
{

    /**
     * @var int 猫id
     */
    public $catId;
}

DogEvent.php:

<?php

/**

* 该Event 封装了与事件相关的有关数据,并提供一些功能函数作为辅助.

*/

namespace webserver\event\devTestEvent\testEvent;

use yii\base\Event;

/**
* Class DogEvent
* @package webserver\event\devTestEvent\testEvent
*/
class DogEvent extends Event
{

    /**
     * @var int 狗id
     */
    public $dogId;
}

MouseEvent.php:

<?php

/**

* 该Event 封装了与事件相关的有关数据,并提供一些功能函数作为辅助.

*/

namespace webserver\event\devTestEvent\testEvent;

use yii\base\Event;

/**
* Class MouseEvent
* @package webserver\event\devTestEvent\testEvent
*/
class MouseEvent extends Event
{

    /**
     * @var int 老鼠id
     */
    public $mouseId;
}

猜你喜欢

转载自blog.csdn.net/zhoupenghui168/article/details/80682945
今日推荐