Как наиболее рационально обновлять данные в моделях Laravel?

Стоит задача - для товаров сделать цены с возможностью конвертации в зависимости от курса валют.
Данные стоимости товаров и курса валют хранятся в разных таблицах имеющие связь один ко многим.
Для хранения данных о стоимости товаров в таблице созданы поля:
  • ‘base_price’ – Базовая цена товара, стоимость в рублях, долларах, евро
  • ‘currency’ – Тип, в какой валюте задана цена: в рублях RUB, в евро EUR или долларах USD
  • ‘price’ – конвертированная цена, с учетом текущего курса валюты.


Валюты обновляются ежедневно по данным ЦБ. Так как курсы валют меняются ежедневно, то и конвертацию заданных в валюте цен необходимо производить минимум раз в сутки.

На первый взгляд проблем нет, получить данные товаров где тип валюты не рубли, (‘currency’ != RUB), и в цикле дергать модели умножать базовую цену на текущий курс и сохранять обновления.

Но как то не рационально получается: огромное количество запросов к базе данных!

Прошу совета сообщества, есть какие-либо способы обновлять данные моделей более оптимально, с наименьшим обращением к базе данных?
  • Вопрос задан
  • 143 просмотра
Решения вопроса 1
@voland700 Автор вопроса
Благодарю Всех за помощь и информацию в решении задачи.

Учитывая, что данная информация возможно будет полезна для других, опишу выбранный мною способ решения.
Действительно, задачу регулярного обновления цен в зависимости от курса валют, можно решить разными способами. Для себя я выбрал способ обновления данных с использованием сырых raw запросов к базе данных. Учитывая, что данные курса валют обновляются не часто, только раз в сутки – считаю это будет оптимальным, не ресурсозатратным способом.

Данные товаров, в том числе их стоимости, хранятся в таблице ‘ product’, в которой так же содержаться поля для определения цены товара:
  1. ‘base_price’ – Базовая цена товара, стоимость в рублях, долларах, евро
  2. ‘currency’ – Тип, в какой валюте задана базовая цена: в рублях RUB, в евро EUR или долларах USD
  3. ‘price’ – конвертированная цена, с учетом текущего курса валюты.

5ff458415c119314189916.jpeg

Свежие данные о курсе валют получаются по API Центрбанка РФ и сохраняются в таблице ‘currency’.
5ff4585ae2d92902315016.jpeg
В контроллере получаю коллекцию и преобразую в массив с необходимыми данными о типе валюты, номинале и значении действующего курса.
$currency = Currency::select('currency', 'Nominal', 'value')->get()->keyBy('currency')->toArray();


Затем с помощью RAW запросов обращаюсь к базе для обновления каждого типа валюты. На пример, для товаров, базовая цена которых задана в ЕВРО (‘currency’ = 'EUR'), обновление данных будет происходить следующим запросом:
$countUpdate = DB::update("UPDATE `product` SET `price` = (`base_price` * ?)  WHERE `currency`='EUR'", [ $currency['EUR']['value'] ]);


То есть из таблицы товаров ("UPDATE `product`) выбираются данные товаров где поле ‘currency’ – тип валюты, задано как (WHERE `currency`='EUR'), и для поля `price` устанавливаются значения, где данные базовой цены умножаются на сумму действующего курса валюты (`price` = (`base_price` * $currency['EUR']['value']).

Таким образом, четырьмя аналогичными запросами происходит конвертация в рубли и обновление цен товаров, цена которых задана в валюте. Используя функции MySQL ELT() и FIELD() данные запросы можно объединить в один.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Fernus
@Fernus
Техник - Механик :)
1. Сделать функцию, которая будет на вход получать значение цены и тип валюты...а далее умножать на курс этой валюты при выводе...
2. Сам курс можно обновлять раз в какое-то время (хоть раз в 10 минут) - не дорогостоящая операция;
3. В том месте, где будет использоваться цена, использовать функцию из пункта 1.

Операция умножения при выводе много ресурсов не потратит...
Ответ написан
New_Horizons
@New_Horizons
Бред:
по одному update запросу на каждую валюту, типа того:
update `products`
set `price` = (`base_price` * ?)
where `currency` = 'EUR';

Где ? - курс.
Ответ написан
@kandrash
Кратко о себе
Вам верно ответили и N и Илья . На чистом Eloquent без raw запроса вы ничего не оптимизируете.

1 вариант. Ответ N это акцессоры в модели. Доки.
2 вариант. Ответ Илья это raw запрос. Доки.
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы