Как реализовать индивидуальные цены в Yii2?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Закрыто
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Как реализовать индивидуальные цены в Yii2?

Сообщение MarkL »

Задача: реализовать для некоторых пользователей индивидуальные цены на услуги. Не для каждой услуги может быть своя индивидуальная цена(то есть, при отсутствии индивидуальной цены выводить стандартную).

Упрощенная схема таблиц:
Изображение

Какие идеи/подходы обдумывал/советовали:

1. Использование поведения AttributeBehaivor вместе с событием "afterFind". Проблема в том, что данное поведение обрабатывает индивидуально каждую отдельную запись базы данных, и при получении индивидуальных цен генерируется соответствующее количество запросов. Код импорта поведения в модель Service: https://pastebin.com/DAqpDLaS, код IndividualServicePriceBehavior: https://pastebin.com/DAqpDLaS
2. Реализовывать SQL-запрос вида:

Код: Выделить всё

SELECT `services`.*, `prices`.`amount` FROM `services` LEFT JOIN `prices` ON `prices`.`service_id` = `services`.`id` AND `prices`.`user_id` = 100
Пример с AR:

Код: Выделить всё

Services::find()->select(['services.*', 'prices.amount'])->leftJoin('prices', ['AND','services.id = prices.amount',['prices.user_id' => Yii::$app->user->id],])->asArray()->all();
Но при таком подходе для каждой услуги должна быть индивидуальная цена, иначе в ячейке цены будет null.

3. Организовать отдельный метод, куда будет помещаться результат выполнения запроса цены, получать индивидуальные цены по ID пользователя и в цикле изменять цену услуг, в итоге возвращать объект с измененными ценами. Тут ряд минусов начиная от того, что придется делать методы для многих вариаций, проблемы с joinWith, а также небезопасно.
someweb
Сообщения: 552
Зарегистрирован: 2017.03.09, 10:12

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение someweb »

Обычный hasOne, а в модели

Код: Выделить всё

public function getPrice() 
{
    return $this->individual_price->price ?? $this->price;
}
Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа. Роберт Шекли.
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение MarkL »

someweb писал(а): 2018.10.07, 11:59 Обычный hasOne, а в модели

Код: Выделить всё

public function getPrice() 
{
    return $this->individual_price->price ?? $this->price;
}
Спасибо за ответ, действительно надо было копать в эту сторону, все на поверхности. Не знаю что со мной не так в последнее время, такие задачи не должны вызывать нужду создания темы на форуме, хотя бы должно решение в голову приходить во время написания.

В плане Вашего подхода: тут нюанс в том, что связь услуг к индивидуальными услугам много к одному, так как для одной услуги может быть несколько индивидуальных цен для разных пользователей. Я при выборке делаю фильтр по user_id, т.е. на примере:

Код: Выделить всё

['individualServices' => function (\yii\db\ActiveQuery $query) {
                            $query->where(['user_id' => $user_id]);
                            }]
И реализация getPrice():

Код: Выделить всё

    public function getPrice()
    {
        return empty($this->uniqueServices->{0}->price) ?? $this->price;
    }
Но она как-то кажется "костыльной", возможно есть лучше варианты?
andku83
Сообщения: 988
Зарегистрирован: 2016.07.01, 10:24
Откуда: Харьков

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение andku83 »

MarkL писал(а): 2018.10.08, 03:02 В плане Вашего подхода: тут нюанс в том, что связь услуг к индивидуальными услугам много к одному, так как для одной услуги может быть несколько индивидуальных цен для разных пользователей...
По вашей структуре БД в отношении одного пользователя связь hasOne():

Код: Выделить всё

    public function getIndividualPrice()
    {
        return $this->hasOne(IndividualPrice::class, ['service' => 'id'])
            ->andWhere(['user_id' => Yii::$app->user->id]);
    }
А вот для админки вы можете использовать hasMany - getIndividualPrices()
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение MarkL »

andku83 писал(а): 2018.10.08, 14:47
MarkL писал(а): 2018.10.08, 03:02 В плане Вашего подхода: тут нюанс в том, что связь услуг к индивидуальными услугам много к одному, так как для одной услуги может быть несколько индивидуальных цен для разных пользователей...
По вашей структуре БД в отношении одного пользователя связь hasOne():

Код: Выделить всё

    public function getIndividualPrice()
    {
        return $this->hasOne(IndividualPrice::class, ['service' => 'id'])
            ->andWhere(['user_id' => Yii::$app->user->id]);
    }
А вот для админки вы можете использовать hasMany - getIndividualPrices()
Столкнулся с проблемой, что в объекте отдает:

Код: Выделить всё

["individualPrice"]=>
  NULL
При этом в _related лежит верный объект:

Код: Выделить всё

["_related":"yii\db\BaseActiveRecord":private]=>
  array(1) {
    ["individualPrice"]=>
    object(common\models\UniqueService)#165 (10) {
      ["_attributes":"yii\db\BaseActiveRecord":private]=>
      array(4) {
        ["id"]=>
        int(12)
        ["user_id"]=>
        int(4296)
        ["service_id"]=>
        int(1)
        ["price"]=>
        float(1.44)
      }
...
Но он обозначен, как приватный. Если применять asArray() тогда отдает с нужным объектом, но мне надо работать с объектом AR для GridView и прочего.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение ElisDN »

Убрать поле public $individualPrice
Аватара пользователя
MarkL
Сообщения: 68
Зарегистрирован: 2017.07.05, 20:37

Re: Как реализовать индивидуальные цены в Yii2?

Сообщение MarkL »

ElisDN писал(а): 2018.10.23, 16:18 Убрать поле public $individualPrice
Спасибо, помогло! Вы, как всегда, прекрасны.
Закрыто