M
M
Mark2018-06-07 17:48:26
Yii
Mark, 2018-06-07 17:48:26

How to implement a one-time sql query when using Behaivors in a model?

I am implementing a module for unique prices, for this I decided to use the priceAttributeBehavior attribute in the model . The logic is simple: a list of individual prices (UniqueService) by user ID is obtained, and it is compared with the ID of the current service, if there is one in the collection - the standard price is replaced by an individual one. The problem is that in this way, when checking each service, the same SQL query with individual prices is called each time. From thoughts only to use caching, but this is some kind of crutch. PS It is also interesting how it is possible to implement disabling the call of this behavior, for example it will be useful in the admin panel, and if the user is not authorized. With the first option from the ideas for now, inherit the model
Serviceand define the behavior with unique prices in the child class, and call it in the right places, and on the second, make a check in the body getValue()for isGuest().
UniqueService, fields: id, user_id, service_id, price.
Behaivors in the Service model:

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};
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Elena Stepanova, 2018-06-07
@Insolita

to disable any behavior, you can call To do this, you must specify the behavior with the name

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

In principle, caching is logical if individual prices are assigned/changed less frequently.
But the structure of your tables is not entirely clear, perhaps instead of behavior it would be more appropriate to use a regular relation

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question