Кешування в 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 проблеми? потрібний додатковий функціонал?
Тоді напишіть мені через форму зворотного зв'язку, і я постараюся вам допомогти.

Напишіть коментар

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *