2016-04-07 7 views
0

Hat jemals jemand einen ActiveRecord-Ereignishandler so binden müssen, dass er nur in bestimmten Szenarien ausgelöst wird? In einer idealen Welt würde die Methode ActiveRecord on() auch einen Parameter $ scenics nehmen und den Handler nur auslösen, wenn ActiveRecord dieses Szenario zum Zeitpunkt des Ereignisses verwendet. Aber da dies nicht der Fall ist, suche ich nach einer sauberen und zuverlässigen Methode, um diese Art von Funktionalität zu implementieren.Yii2: ActiveRecord-Ereignisse, die nur für ein Szenario ausgelöst werden

Edit: Dies muss mit beliebigen Ereignis, einschließlich der integrierten Ereignisse durch das Yii-Framework ausgelöst ausgelöst werden (z. B. ActiveRecord::EVENT_AFTER_INSERT).

+1

Ich denke, Sie können '\ yii \ base \ Event' erweitern und Ihre eigene Methode' onScenario() 'hinzufügen. Es ist das gleiche wie 'on()', aber ein zusätzliches Argument mit Szenarien erhalten. Sie können es wie die Methode 'scenarios()' in ActiveRecord verwenden. Außerdem müssen Sie die Methode 'trigger()' überschreiben und vor dem Parent-Aufruf eine Szenario-Prüfung hinzufügen. – SiZE

Antwort

0

Diese Verbesserung meines ersten Kommentars.

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; 
       } 
      } 
     } 
    } 
} 
+0

Leider funktioniert dies nur mit manuell ausgelösten Ereignissen (ich brauche das nicht). Es funktioniert nicht mit irgendwelchen automatisch ausgelösten eingebauten Ereignissen (wie zum Beispiel '\ yii \ db \ AfterSaveEvent' in' \ yii \ db \ ActiveRecord'), was ich wirklich brauche. – mae

Verwandte Themen