Установка события в конфигурации приложения.
  • 413

Закрепление обработчика события обновления кэша sitemap.xml в конфигурационном файле yii2.

Автор: admin | 06 июня (Ср.) 2018г. в 14ч.07м.

Раньше я написал статью о том, как сделать генератор карты сайта sitemap.xml на yii2.
При этом сгенерированная карта сайта кэшируется на 12 часов.
Yii::$app->cache->set('sitemap', $xml_sitemap, 60*60*12);// $xml_sitemap - сгенерированная карта сайта​

Но как же быть, если добавляется
новая статья и хотелось бы, чтобы эта статья сразу появилась в sitemap.xml. Нужно обновить кэш.

Для этого нужно кэш сбросить так:
Yii::$app->cache->delete('sitemap');​
 
И это нужно сделать в модели \yii\db\ActiveRecord , которая обробатывает создания новой
статьи и содержит CRUD методы (например: backend\models\blog\BlogArticles'). Можно добавитьсброс кэша в public function beforeSave($insert){}

Привязка обработчика события в конфиге приложения.

Но лучше будет создать обработчик события afterInsert и привязать его прямо в конфигурации приложения. В моем случае, я использую advenced шаблон приложения.
Поэтому я буду присоединять обработчики событий \yii\db\ActiveRecord в main.php в backend части. Моя модель, которая учавствует в CRUD новых статей наследует ActiveRecord. Создается объект модели в контроллере, что обробатывает форму создания/обновления/удаления. Поэтому обработку событий буду навешивать на класс, а не на объект.
yii\base\Event::on(backend\models\blog\BlogArticles::className(), yii\db\ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

yii\base\Event::on(backend\models\blog\BlogArticles::className(), yii\db\ActiveRecord::EVENT_AFTER_UPDATE, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

yii\base\Event::on(backend\models\blog\BlogArticles::className(), yii\db\ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

return [
    'id' => 'app-backend',
'components' => [
    //...
    'frontendCache' => [
            'class' => 'yii\caching\FileCache',
            'cachePath' => Yii::getAlias('@frontend') . '/runtime/cache'
    ],
],​
//...

Так как конфиг находится в части backend/config/main.php, а контроллер карты сайта во frontend, и кэш хранится в папке runtime во frontend части, то нужно очищать именно этот кэш.
Для этого и создается этот компонент:

'frontendCache' => [
      'class' => 'yii\caching\FileCache',
      'cachePath' => Yii::getAlias('@frontend') . '/runtime/cache'
],

Обратите внимание на место, где указаны обработчики событий в main.php ,а именно то что нужно обработчики прописать вне return и до него. Можно и нужно сократить код указав директиву use для пространств имен, что используются.

use backend\models\blog\BlogArticles;
use yii\db\ActiveRecord;
use yii\base\Event;

Event::on(BlogArticles::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

Event::on(BlogArticles::className(), ActiveRecord::EVENT_AFTER_UPDATE, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

Event::on(BlogArticles::className(), ActiveRecord::EVENT_AFTER_DELETE, function ($event) {
    \Yii::$app->frontendCache->delete('sitemap');
});

return[
//...конфиг
]

Теперь при создании новой статьи обновляется кэш по нужному ключу и карта сайта обновляется актуальной
информацией.

Рефакторинг кода.

Думаю, лучше было бы перенести обработку событий из конфига в файл предзагрузки, тем самым разгрузить конфигурацию и улучшить структуру приложения.
Создадим файл common\components\events\EventBootstrap, который реализует интерфейс yii\base\BootstrapInterface ,в который и перенесем все обработчики из конфига:
namespace common\components\events;

use yii;
use yii\base\BootstrapInterface;
use yii\base\ErrorHandler;
use yii\di\Container;
use backend\models\blog\BlogArticles;
use yii\db\ActiveRecord;
use yii\base\Event;
/**
 * Description of SetUp
 *
 * @author Sergio Codev <codev>
 */
class EventBootstrap implements BootstrapInterface{
    
    public function bootstrap($app){
        
        $container = \Yii::$container;
        
        $this->setSitemapEvents();
        
    }
    
    private function setSitemapEvents() {
        $events = [
            ActiveRecord::EVENT_AFTER_INSERT, 
            ActiveRecord::EVENT_AFTER_UPDATE,
            ActiveRecord::EVENT_AFTER_DELETE
        ];

        foreach ($events as $eventName) {
            Event::on(BlogArticles::className(), $eventName, function ($event) {
                \Yii::$app->frontendCache->delete('sitemap');
            });
        }
    }

}   
​

Подключим этот файл в конфиг приложения common/config/main.php в массив с ключем bootstrap:

return [
   'components' => [
        /////тут компоненты
   ],

   'bootstrap' => [
        'common\components\events\EventBootstrap',
        //тут могут быть другие файлы автозагрузки
        ],  
];
В конфиге backend/config/main.php оставим лишь назначение компонента frontendCache, а все события уберем или закомментим. Теперь обработка событий перенесена в отдельный файл и конфигурация стала немного "чище"...

Читайте также из этой серии:

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

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

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