Реализовываю модуль уникальных цен, для этого решил использовать
AttributeBehavior
в модели для атрибута
price.
Логика проста: получается список индивидуальных цен(UniqueService) по ID пользователя, и сравнивается он с ID текущей услуги, если такой имеется в коллекции - цена стандартная заменяется на индивидуальную.
Проблема в том, что таким образом при проверке каждой услуги вызывается каждый раз одинаковый SQL-запрос с индивидуальными ценами. Из мыслей лишь использовать кэширование, но это какой-то костыль выходит.
P.S. Также интересно, как можно реализовать отключение вызова данного поведения, к примеру это будет полезно в администраторской панели, и если пользователь неавторизован. Со первым вариантом из идей пока отнаследовать модель
Service
и поведение с уникальными ценами определить в дочерний класс, и вызывать нужных местах, а по второму сделать проверку в теле
getValue()
на
isGuest()
.
UniqueService, поля: id, user_id, service_id, price.
Behaivors в модели Service:
public function behaviors()
{
return [
[
'class' => IndividualServicePriceBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_AFTER_FIND => 'price',
],
'priceAttribute' => 'price',
'idAttribute' => 'id',
'individualPrices' => UniqueService::find()->where(['user_id' => Yii::$app->user->id])->all(),
],
];
}
IndividualServicePriceBehavior
namespace common\behaviors;
use yii\behaviors\AttributeBehavior;
class IndividualServicePriceBehavior extends AttributeBehavior
{
/**
* @var \common\models\UniqueService
*/
public $individualPrices;
public $priceAttribute;
public $idAttribute;
public function getValue($event)
{
foreach ($this->individualPrices as $individualPrice) {
if($individualPrice['service_id'] == $this->owner->{$this->idAttribute}) {
return $this->owner->{$this->priceAttribute} = $individualPrice['price'];
}
}
return $this->owner->{$this->priceAttribute};
}
}