@MarkLb

Как реализовать единоразовый sql-запрос при использовании Behaivors в модели?

Реализовываю модуль уникальных цен, для этого решил использовать 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};
    }
}
  • Вопрос задан
  • 67 просмотров
Пригласить эксперта
Ответы на вопрос 1
Insolita
@Insolita
Отчаянная домохозяйка
для отключения любого поведения можно вызвать
$model->detachBehavior('behaviorName');
Для этого надо указывать behavior c именем

public function behaviors()
    {
        return [
           'behaviorName'=> [
                'class' => IndividualServicePriceBehavior::className(),
                /// ,,,
            ],
        ];
    }


В принципе кеширование - логично, если индивидульные цены назначаются/меняются не так часто.
Но не совсем понятна структура ваших таблиц , возможно вместо поведения уместнее будет использовать обычную реляцию
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы