Как работать с  событиями yii\db\Connection в момент соединения с БД в Yii2.
  • 703

Как работать с событиями в момент соединения с БД в Yii2.

Автор: admin | 14 июня (Чт.) 2018г. в 11ч.37м.

События, о которых пойдет речь.

EVENT_AFTER_OPEN - событие, которое запускается после установления соединения с БД.
 
EVENT_BEGIN_TRANSACTIONсобытие, которое запускается непосредственно перед началом транзакции верхнего уровня

EVENT_COMMIT_TRANSACTIONсобытие, которое запускается в момент завершения транзакции верхнего уровня

EVENT_ROLLBACK_TRANSACTIONсобытие, которое запускается при откате транзакции верхнего уровня.

В конфигурационном файле как в базовом, так и в расширенном шаблоне yii2 есть настройка для работы с базой
данных такого вида:
'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=your_db_name',
            'username' => 'root',
            'password' => 'your_pass',
            'charset' => 'utf8',
],

//...другие компоненты​

В расширенном шаблоне (advensed yii2) эти настройки нежат в файле по пути ./common/config/main-local.php
, а в basic yii2 в ./config/web.php

Тут оприделяются настройки соединения, такие как пароль и имя ползователя, кодировка, вид базы данных и другие.
yii\db\Connection представляет собой адаптер для соединения с базой данных через PDO.

События соединения с БД в yii2.

В классе yii\db\Connection есть четыре события, которые относятся к соединению с базой данных.
Названия этих событий хранят четыре константы класса:

EVENT_AFTER_OPEN.
EVENT_BEGIN_TRANSACTION.
EVENT_COMMIT_TRANSACTION.
EVENT_ROLLBACK_TRANSACTION.

Из исходников:
class Connection extends Component
{

/**
* @event Event an event that is triggered after a DB connection is established
*/
const EVENT_AFTER_OPEN = 'afterOpen';
/**
* @event Event an event that is triggered right before a top-level transaction is started
*/
const EVENT_BEGIN_TRANSACTION = 'beginTransaction';
/**
* @event Event an event that is triggered right after a top-level transaction is committed
*/
const EVENT_COMMIT_TRANSACTION = 'commitTransaction';
/**
* @event Event an event that is triggered right after a top-level transaction is rolled back
*/
const EVENT_ROLLBACK_TRANSACTION = 'rollbackTransaction';​

Примеры использования событий соединения с БД в yii2.

Событие после открытия соединения с бд yii\db\Connection::EVENT_AFTER_OPEN .
Задается нужная временна зона для БД.
'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=your_db_name',
            'username' => 'root',
            'password' => 'your_pass',
            'charset' => 'utf8',
            'on afterOpen' => function($event) {
            
            
                // $event->sender содержит соединение с базой данных
                $diffGMT = date('P');//Разница с временем по Гринвичу.Например: +02:00
                $event->sender->createCommand("SET time_zone = '{$diffGMT}'")->execute();
            }
],​

Или создаем триггер на изменение каких-либо данных, исходя из условия (не важно какого, главное принцип написания кода):

'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=your_db_name',
            'username' => 'root',
            'password' => 'your_pass',
            'charset' => 'utf8',
            'on afterOpen' => function($event) {
                $expression = new \yii\db\Expression('
                    DROP TRIGGER IF EXISTS `after_delete_view_statistic`;
                    CREATE TRIGGER `after_delete_view_statistic` 
                    AFTER DELETE ON `viewsStatisticArticles` 
                    FOR EACH ROW BEGIN 
                        UPDATE `blogArticles`
                        SET viewCount = (SELECT COUNT(viewsStatisticArticles.id) FROM `viewsStatisticArticles` WHERE viewsStatisticArticles.idArticle = blogArticles.id);
                    END;');

                $event->sender->createCommand($expression)->execute();
            }
],

Далее рассмотрим события транзакций на простом примере.

//Сохраняем объект соединения в переменную
$connection = \Yii::$app->db;

//Назначаем обработчики для событий
$connection->on(\yii\db\Connection::EVENT_BEGIN_TRANSACTION, function ($event) {
    echo \yii\db\Connection::EVENT_BEGIN_TRANSACTION;
});

$connection->on(\yii\db\Connection::EVENT_COMMIT_TRANSACTION, function ($event) {
    echo \yii\db\Connection::EVENT_COMMIT_TRANSACTION;
});

$connection->on(\yii\db\Connection::EVENT_ROLLBACK_TRANSACTION, function ($event) {
    echo \yii\db\Connection::EVENT_ROLLBACK_TRANSACTION;
});
        
$transaction = $connection->beginTransaction();
try {
    $statistic = new ViewsStatisticArticles([
        'idArticle' => $this->id,
        'ip' => \Yii::$app->request->userIP,
    ]);

    if($statistic->save()){
        //при удалении из ViewsStatisticArticles используется триггер для обновления viewCount
        //из main-local.php
        $this->updateCounters(['viewCount' => 1]);
        $transaction->commit();
    }
} catch(Exception $e) {
    $transaction->rollback();
}

В приведенном примере назначается обработка событий транзакции в виде простого echo.
Далее, когда в процессе выполнения кода обработчики будут вызваны на экран, выведется
'beginTransaction commitTransaction'. Ну а при возникновении исключения выведется 'rollbackTransaction'.
$event->sender внутри обработчика события содержится соединение с базой данных (в данном случае!).

Эти события можно применить, например, если после удачного коммита нужно отправить сообщение
пользователю на почту об удачном действии (заказ товара в интернет-магазине) или что-то еще.

А если транзакция не удалась, сохранить важные данные, пришедшие, например с формы заказа и т.д.
В общем вариантов применения множество.

Приветствую!

Меня зовут Сергей. Я - автор этого блога.

Если Вам был полезен материал на моем сайте, поддержите пожалуйста мой проект, чтобы о нем узнали другие люди - кликните plizz :) на иконку в соц. сети, чтобы поделиться материалом с другими.