Доброго времени суток!
Опишу кратко задачу.
Есть интернет-магазин, есть несколько магазинов по всей России, у каждого поставщика свои контакты, свои новости, свои цены и остатки на товары. Город с магазином у посетителя выбирается по гео базе, записывается в куку (если еще не указан в куках или в профиле).
Задача: Нужно сделать, чтобы вся получаемая система могла работать как с одним магазином, так и со, скажем, 100 магазинами.
Вопросы:
1. Как лучше реализовать хранение привязки к дилеру?
а) прямо в таблице добавлять поле dealer_id?
б) делать отдельную таблицу с dealer_assignment? (тогда выйдет еще минимум с десяток таблиц, ведь entities много дилерозависимых)
2. Как лучше делать выборку из базы при наличии выбранного дилера?
а) Пройтись по всем ActiveQuery и добавить правила - если дилер - то andWhere().. и т.д.
б) Сделать отдельный trait и прикрепить ко всем нужным моделям и разруливать дилеров там.
в) Отдельный сервисный слой для этого? Какой (в функциональном плане)?
И самый главный вопрос:
Как бы Вы построили такую архитектуру, будь у Вас такая задача?
Заранее спасибо за советы.
Совет по архитектуре магазина с несколькими филиалами
Re: Совет по архитектуре магазина с несколькими филиалами
1. Через dealer_id.
2. Product::find()->forDealer($id)->..., с return $this->andFilterWhere(['dealer_id' => $id]) внутри.
3. Также, как простой магазин, только с DealerMiddleware и $request->getAttribute('dealer').
2. Product::find()->forDealer($id)->..., с return $this->andFilterWhere(['dealer_id' => $id]) внутри.
3. Также, как простой магазин, только с DealerMiddleware и $request->getAttribute('dealer').
Re: Совет по архитектуре магазина с несколькими филиалами
Спасибо!
Меня волнует вопрос, что необходимо прописать forDealer($id) во многих местах и где-то могу забыть. Возможно ли подобное прописать для всех запросов касаемо модели в одном месте? В отдельном классе, который расширяет ActiveQuery, или практика не очень хороша?
Возможно чуть подробнее описать суть вот этой прослойки? DealerMiddleware
Re: Совет по архитектуре магазина с несколькими филиалами
Также кто-то забудет и отнаследуется от ActiveQuery вместо DealerActiveQuery. Это обнаружить тоже сложно.
Код: Выделить всё
namespace App\Http\Middleware;
use HansOtt\PSR7Cookies\SetCookie;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\RedirectResponse;
class DealerMiddleware
{
private $default;
private $timeout;
public function __construct($default, $timeout)
{
$this->default = $default;
$this->timeout = $timeout;
}
public function __invoke(ServerRequestInterface $request, callable $next)
{
if ($dealer = $request->getQueryParams()['dealer'] ?? null) {
return $this->redirectWithDealerCookie($request, $dealer);
}
$dealer = $request->getCookieParams()['dealer'] ?? $this->default;
return $next($request->withAttribute('dealer', $dealer));
}
private function redirectWithDealerCookie(ServerRequestInterface $request, $dealer)
{
$cookie = new SetCookie('dealer', $dealer, time() + $this->timeout);
$response = new RedirectResponse($request->getUri()->withQuery(''));
return $cookie->addToResponse($response);
}
}
Re: Совет по архитектуре магазина с несколькими филиалами
Редирект делать в beforeRequest или beforeAction, а читать из cookies уже в контроллере (напрямую или в хелпере).
Re: Совет по архитектуре магазина с несколькими филиалами
Необходимо будет класс разнести по разным функциям? Так как в примере класса эти две задачи делаются в одной функции.. (__invoke)
В принципе же реально этот класс использовать в том в виде, какой он есть - в Yii.