zhoupenghui 2018-05-30 11:56:39 2383次浏览 1条回复 0 0 0

本案例参考 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'; $.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;

} `

您需要登录后才可以回复。登录 | 立即注册