Events Yii2:仅在场景中触发的ActiveRecord事件
有没有人需要绑定ActiveRecord事件处理程序,使其仅在特定场景中触发 在理想情况下,ActiveRecordEvents Yii2:仅在场景中触发的ActiveRecord事件,events,activerecord,yii2,scenarios,Events,Activerecord,Yii2,Scenarios,有没有人需要绑定ActiveRecord事件处理程序,使其仅在特定场景中触发 在理想情况下,ActiveRecordon()方法还将接受$scenarios参数,并仅在事件发生时ActiveRecord正在使用该场景时触发处理程序。但既然不是这样,我正在寻找一种干净、可靠的方法来实现这种功能 编辑:这需要处理任何事件,包括由Yii框架触发的内置事件(例如插入后的事件)。这是我第一次评论的改进 class ScenarioEvent extends \yii\base\Event { pr
on()
方法还将接受$scenarios参数,并仅在事件发生时ActiveRecord正在使用该场景时触发处理程序。但既然不是这样,我正在寻找一种干净、可靠的方法来实现这种功能
编辑:这需要处理任何事件,包括由Yii框架触发的内置事件(例如插入后的事件)。这是我第一次评论的改进
class ScenarioEvent extends \yii\base\Event
{
private static $_events = [];
public static function onScenario($scenario, $class, $name, $handler, $data = null)
{
// You may use foreach if you wil use many scenarios for event
if (!isset(self::$_scenarios)) {
self::$_scenarios[$scenario] = [];
}
self::$_scenarios[$scenario][$name][] = $class;
return static::on($class, $name, $handler, $data);
}
public static function trigger($class, $name, $event = null)
{
if (
// If event is null assumed that it has no sender with scenario
$event === null
|| empty(self::$_scenarios[$event->sender->scenario][$name])
) {
parent::trigger($class, $name, $event);
} else {
$classes = array_merge(
[$class],
class_parents($class, true),
class_implements($class, true)
);
foreach ($classes as $class) {
if (in_array($class, self::$_scenarios[$event->sender->scenario][$name])) {
parent::trigger($class, $name, $event);
break;
}
}
}
}
}
我认为您可以扩展
\yii\base\Event
并在Scenario()上添加自己的方法。它将与()上的相同
,但会在场景中获得一个附加参数。您可以像在ActiveRecord中使用方法scenarios()
一样使用它。您还需要重写trigger()
方法,并在父调用之前添加场景检查。遗憾的是,这可能只适用于手动触发的事件(我不需要)。它不适用于任何自动触发的内置事件(例如\yii\db\AfterSaveEvent
中的\yii\db\ActiveRecord
),这正是我实际需要的。