Кэширование в Yii2 и поведения (behavior)

Кэширование в Yii2 и поведения (behavior)

Что делать, если Вам потребовалось внедрить стандартный функционал (к примеру кэширование данных) к некоторым стандартным моделям? Мне в данном случае, на помощь пришел behavior и его великолепные возможности.

Если вкратце, то behavior (поведение), в фреймворке yii2, позволяет расширять контроллеры и модели (или все то что было наследовано от класса «Component») своими дополнительными методами. Работает по аналогии с трейтами в PHP, но не то же самое. Если вас интересует более детальное определение и возможности, для этого загляните на официальный сайт фреймворка.

В данной же статье, я опишу свой небольшой опыт совместной работы кэширования, моделей и поведений.

История. На определенном этапе разработки, потребовалось внедрить кэширование к четырем стандартным моделям:

  • Рубрикам
  • Категориям
  • Регионам
  • Городам

Все они имеют стандартную структуру таблиц, за исключением таблиц «категорий» и «городов». В них присутствует родительский ID (рубрики / региона).

Само наше поведение имеет следующий код:

class CachedBehavior extends Behavior
{
	public $cache_pref;
	
	public $from = 'id';
	public $to = 'title';
	public $group;
	
    public function events()
    {
        return [
			ActiveRecord::EVENT_AFTER_INSERT => 'deleteCache',
			ActiveRecord::EVENT_AFTER_UPDATE => 'deleteCache',
			ActiveRecord::EVENT_AFTER_DELETE => 'deleteCache',
        ];
    }

    public function deleteCache()
    {
		Yii::$app -> cache -> delete($this -> cache_pref);
    }
	
	public function getCacheAsTree()
	{
		return ArrayHelper::map($this -> getCache(), $this -> from, $this -> to, $this -> group);
	}
	
	public function getCacheList()
	{
		return ArrayHelper::map($this -> getCache(), $this -> from, $this -> to);
	}
	
	public function getCacheById($id)
	{
		$a = $this -> getCache();
		
		if(isset($a[$id]))
		{
			return $a[$id];
		}
		return [];
	}
	
	public function getCache()
	{
		$Cache = Yii::$app -> cache;
		$a = $Cache -> get($this -> cache_pref);

		if($a === false)
		{
			$a_ = (new Query())
			-> select('*')
			-> from($this -> owner -> tableName())
			-> orderBy('`order` ASC, `title` ASC')
			-> all();
			
			$a = [];
			foreach ($a_ as $v)
			{
				$a[$v[$this -> from]] = $v;
			}
			
			$Cache -> set($this -> cache_pref, $a, HelperDate::WEEK);
		}
		
		return $a;
	}
}

Где:

public $cache_pref;
	
public $from = 'id';
public $to = 'title';
public $group;

параметры нашего поведения, некоторые (стандартные для всех случаев) установленные по умолчанию.

Каждая модель имеет свой префикс для $cache_pref кэша (но можно использовать и названия таблицы, обратившись к ней как к «$this -> owner -> tableName()»)

Через события, указываем когда нам нужно удалить данные кэша:

public function events()
{
	return [
		ActiveRecord::EVENT_AFTER_INSERT => 'deleteCache',
		ActiveRecord::EVENT_AFTER_UPDATE => 'deleteCache',
		ActiveRecord::EVENT_AFTER_DELETE => 'deleteCache',
	];
}

а именно при создании новой записи, редактировании существующий или удалении какой-то.

Все что начинается с «get» ниже по коду, идут методы работы с кэшем. И их можно использовать обратившись к методу модели.

К примеру. Подключаем наше поведение к модели городов:

class TerritoryCityModel extends ActiveRecord
{
	public function behaviors()
	{
		return [
			'CachedBehavior' => [
				'class' => CachedBehavior::className(),
				'cache_pref' => 'territory-city',
				'group' => 'territory_region_id',
			],
		];
	}

	public static function tableName()
	{
		return '{{%territory_city}}';
	}
}

В коде, к методам нашего поведения можно будет обратиться следующим образом:

//Отобразить деревом
(new TerritoryCityModel()) -> getCacheAsTree();

//Или отобразить списком
(new TerritoryCityModel()) -> getCacheList()

//Или как-то иначе...

Еще одна замечательная идея использования поведений, это вынесение в них не стандартных методов валидации.

Поделиться в соцсетях:

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

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *