├── .gitignore ├── CHANGELOG.md ├── README.md ├── composer.json └── src ├── components ├── EventListener.php └── EventListenerInterface.php ├── listeners └── Listener.php └── observers ├── ActiveRecordObserver.php └── Observer.php /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE project files 2 | .idea 3 | nbproject 4 | .buildpath 5 | .project 6 | .settings 7 | 8 | # windows thumbnail cache, Mac DS_Store 9 | Thumbs.db 10 | .DS_Store 11 | Desktop.ini 12 | 13 | # composer vendor dir 14 | /vendor 15 | 16 | # composer itself is not needed 17 | composer.phar 18 | composer.lock 19 | 20 | # phpunit itself is not needed 21 | phpunit.phar 22 | # local phpunit config 23 | /phpunit.xml 24 | tests/_output/* 25 | tests/_support/_generated 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ===================== 3 | 4 | v1.0.1 5 | --------------------- 6 | * Fix wrong Listener file name 7 | 8 | v1.0 9 | --------------------- 10 | * Component, Listener, Observer 11 | * ActiveRecordObserver ready-to-use class 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 |

Yii2 Event Listener

6 |
7 |

8 | 9 | Simple event listeners registration component and base abstract classes to implement Linstener or Observer. 10 | 11 | ## Installation 12 | 13 | The preferred way to install this extension is through composer. 14 | 15 | Either run 16 | 17 | ```bash 18 | composer require --prefer-dist justcoded/yii2-event-listener "*" 19 | ``` 20 | 21 | or add 22 | 23 | ``` 24 | "justcoded/yii2-event-listener": "*" 25 | ``` 26 | 27 | to the require section of your composer.json. 28 | 29 | ### Component Setup 30 | 31 | To use the Event Listener Component, you need to configure the components array in your application configuration: 32 | 33 | ```php 34 | 'components' => [ 35 | 'listener' => [ 36 | 'class' => \justcoded\yii2\eventlistener\components\EventListener::class, 37 | 'listeners' => [ 38 | ... 39 | ], 40 | 'observers' => [ 41 | ... 42 | ], 43 | ], 44 | ], 45 | ``` 46 | 47 | and add component name to bootstrap array 48 | 49 | ```php 50 | 'bootstrap' => ['log', 'listener'], 51 | ``` 52 | 53 | ## Usage 54 | 55 | ### Listeners 56 | 57 | **Listener** is a single action, which can be performed on some event. To register a listener you need to create a simple class: 58 | 59 | ```php 60 | sender; 82 | 83 | // TODO: write your code here, for example, send user greeting email after it was registered or created. 84 | } 85 | } 86 | 87 | ``` 88 | 89 | After that you need to register it within a component inside 'listeners' config array: 90 | 91 | ```php 92 | 'components' => [ 93 | 'listener' => [ 94 | 'class' => \justcoded\yii2\eventlistener\components\EventListener::class, 95 | 'listeners' => [ 96 | \app\models\User::class => [ 97 | \app\models\User::EVENT_AFTER_INSERT => \app\listeners\SendUserGreeting::class, 98 | ], 99 | ], 100 | ], 101 | ], 102 | ``` 103 | 104 | ### Observers 105 | 106 | Observer is a class, which can subscribe to several events of the same model. To create an 107 | Observer you need to extend it from a basic Observer class and create `events()` method and methods to 108 | handle these events. 109 | 110 | Example: 111 | 112 | ```php 113 | 'before', 129 | SiteController::EVENT_AFTER_ACTION => 'after', 130 | ]; 131 | } 132 | 133 | /** 134 | * Handle before action event 135 | * 136 | * @param Event $event 137 | * 138 | * @return void 139 | */ 140 | public function before(Event $event) 141 | { 142 | /* @var SiteController $sender */ 143 | $sender = $event->sender; 144 | 145 | // TODO: write your code here. 146 | } 147 | 148 | /** 149 | * Handle after action event 150 | * 151 | * @param Event $event 152 | * 153 | * @return void 154 | */ 155 | public function after(Event $event) 156 | { 157 | /* @var SiteController $sender */ 158 | $sender = $event->sender; 159 | 160 | // TODO: write your code here. 161 | } 162 | } 163 | ``` 164 | 165 | After that you need to register it within a component inside 'observers' config array: 166 | 167 | ```php 168 | 'components' => [ 169 | 'listener' => [ 170 | 'class' => \justcoded\yii2\eventlistener\components\EventListener::class, 171 | 'observers' => [ 172 | app\controllers\SiteController::class => \app\observers\SiteControllerObserver::class, 173 | app\models\User::class => \app\observers\UserObserver::class, 174 | ], 175 | ], 176 | ], 177 | ``` 178 | 179 | #### ActiveRevordObserver 180 | 181 | Package also contains a specific class called ActiveRecordObserver. 182 | This class already declared all ActiveRecord events an methods to process them: 183 | 184 | * inserting() 185 | * inserted() 186 | * updating() 187 | * updated() 188 | * deleting() 189 | * deleted() 190 | * validating() 191 | * validated() 192 | * refreshed() 193 | * initialized() 194 | 195 | Example: 196 | 197 | ```php 198 | sender; 220 | 221 | // TODO: write your code here. 222 | } 223 | } 224 | 225 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "justcoded/yii2-event-listener", 3 | "description": "Yii2 Event Listener", 4 | "type": "yii2-extension", 5 | "keywords": [ 6 | "yii2", 7 | "event listener", 8 | "events", 9 | "listeners" 10 | ], 11 | "license": "BSD-3-Clause", 12 | "authors": [ 13 | { 14 | "name": "Alex Prokopenko", 15 | "email": "aprokopenko@justcoded.com" 16 | } 17 | ], 18 | "minimum-stability": "dev", 19 | "require": { 20 | "php": ">=7.0.0", 21 | "yiisoft/yii2": "~2.0.11" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "justcoded\\yii2\\eventlistener\\": "src/" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/components/EventListener.php: -------------------------------------------------------------------------------- 1 | [ 25 | * User::EVENT_AFTER_INSERT => \app\listeners\UserInserted::class 26 | * User::EVENT_AFTER_UPDATE => [ 27 | * \app\listeners\UserUpdated::class, 28 | * \app\listeners\EntityUpdated::class, 29 | * ], 30 | * ], 31 | * 32 | * @var array 33 | */ 34 | public $listeners = []; 35 | 36 | /** 37 | * Specify objects to be observed by observer classes. 38 | * 39 | * Config example 40 | * 41 | * \app\models\User::class => \app\listeners\UserObserver::class, 42 | * \app\models\User::class => [\app\listeners\UserObserver::class, ... ], 43 | * 44 | * @var array 45 | */ 46 | public $observers = []; 47 | 48 | /** 49 | * Bootstrap method to be called during application bootstrap stage. 50 | * 51 | * @param Application $app the application currently running 52 | */ 53 | public function bootstrap($app) 54 | { 55 | $container = \Yii::$container; 56 | $container->setSingleton(EventListenerInterface::class, $this); 57 | } 58 | 59 | /** 60 | * @inheritdoc 61 | */ 62 | public function init() 63 | { 64 | $this->initListeners(); 65 | $this->initObservers(); 66 | } 67 | 68 | /** 69 | * Normalize Config Array 70 | * check value to be array, index values with the same value string 71 | * 72 | * @param array $array 73 | * 74 | * @return array 75 | */ 76 | protected function normalizeConfig($array) 77 | { 78 | foreach ($array as $key => $value) { 79 | if (! is_array($value)) { 80 | $value = [$value]; 81 | } 82 | 83 | $array[$key] = array_combine($value, $value); 84 | } 85 | 86 | return $array; 87 | } 88 | 89 | /** 90 | * Create listener classes and match them to an events based on $this->listeners configuration array. 91 | */ 92 | protected function initListeners() 93 | { 94 | if (empty($this->listeners)) { 95 | return; 96 | } 97 | 98 | // normalize config array. 99 | foreach ($this->listeners as $watchedName => $listeners) { 100 | $this->listeners[$watchedName] = $this->normalizeConfig($listeners); 101 | } 102 | 103 | // init events. 104 | foreach ($this->listeners as $watchedName => $modelEvents) { 105 | foreach ($modelEvents as $eventName => $listeners) { 106 | foreach ($listeners as $listenerClass) { 107 | $listener = new $listenerClass(); 108 | Event::on($watchedName, $eventName, [$listener, 'handle']); 109 | 110 | $this->listeners[$watchedName][$eventName][$listenerClass] = $listener; 111 | } 112 | } 113 | } 114 | } 115 | 116 | /** 117 | * Create observer classes and match them to an events based on $this->observers configuration array. 118 | */ 119 | protected function initObservers() 120 | { 121 | if (empty($this->observers)) { 122 | return; 123 | } 124 | 125 | $this->observers = $this->normalizeConfig($this->observers); 126 | 127 | foreach ($this->observers as $className => $observers) { 128 | foreach ($observers as $observerClass) { 129 | $observer = new $observerClass(); 130 | $events = $observer->events(); 131 | 132 | foreach ($events as $eventName => $methodName) { 133 | Event::on($className, $eventName, [$observer, $methodName]); 134 | } 135 | 136 | $this->observers[$className][$observerClass] = $observer; 137 | } 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/components/EventListenerInterface.php: -------------------------------------------------------------------------------- 1 | 'inserted', 20 | * ] 21 | * 22 | * @return array 23 | */ 24 | public function events() 25 | { 26 | return [ 27 | ActiveRecord::EVENT_AFTER_FIND => 'found', 28 | ActiveRecord::EVENT_AFTER_INSERT => 'inserted', 29 | ActiveRecord::EVENT_AFTER_UPDATE => 'updated', 30 | ActiveRecord::EVENT_AFTER_VALIDATE => 'validated', 31 | ActiveRecord::EVENT_AFTER_REFRESH => 'refreshed', 32 | ActiveRecord::EVENT_AFTER_DELETE => 'deleted', 33 | ActiveRecord::EVENT_BEFORE_INSERT => 'inserting', 34 | ActiveRecord::EVENT_BEFORE_UPDATE => 'updating', 35 | ActiveRecord::EVENT_BEFORE_VALIDATE => 'validating', 36 | ActiveRecord::EVENT_BEFORE_DELETE => 'deleting', 37 | ActiveRecord::EVENT_INIT => 'initialized', 38 | ]; 39 | } 40 | 41 | public function found(\yii\base\Event $event) 42 | { 43 | } 44 | 45 | public function inserted(\yii\db\AfterSaveEvent $event) 46 | { 47 | } 48 | 49 | public function updated(\yii\db\AfterSaveEvent $event) 50 | { 51 | } 52 | 53 | public function validated(\yii\base\Event $event) 54 | { 55 | } 56 | 57 | public function deleted(\yii\base\Event $event) 58 | { 59 | } 60 | 61 | public function refreshed(\yii\base\ModelEvent $event) 62 | { 63 | } 64 | 65 | public function inserting(\yii\base\ModelEvent $event) 66 | { 67 | } 68 | 69 | public function updating(\yii\base\ModelEvent $event) 70 | { 71 | } 72 | 73 | public function validating(\yii\base\ModelEvent $event) 74 | { 75 | } 76 | 77 | public function deleting(\yii\base\ModelEvent $event) 78 | { 79 | } 80 | 81 | public function initialized(\yii\base\Event $event) 82 | { 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/observers/Observer.php: -------------------------------------------------------------------------------- 1 | 'inserted', 18 | * ] 19 | * 20 | * @return array 21 | */ 22 | abstract public function events(); 23 | } 24 | --------------------------------------------------------------------------------