Совет по архитектуре магазина с несколькими филиалами

Обсуждаем, как правильно строить приложения
Ответить
Аватара пользователя
Йож
Сообщения: 574
Зарегистрирован: 2015.08.26, 03:05

Совет по архитектуре магазина с несколькими филиалами

Сообщение Йож »

Доброго времени суток!

Опишу кратко задачу.

Есть интернет-магазин, есть несколько магазинов по всей России, у каждого поставщика свои контакты, свои новости, свои цены и остатки на товары. Город с магазином у посетителя выбирается по гео базе, записывается в куку (если еще не указан в куках или в профиле).

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

Вопросы:
1. Как лучше реализовать хранение привязки к дилеру?
а) прямо в таблице добавлять поле dealer_id?
б) делать отдельную таблицу с dealer_assignment? (тогда выйдет еще минимум с десяток таблиц, ведь entities много дилерозависимых)
2. Как лучше делать выборку из базы при наличии выбранного дилера?
а) Пройтись по всем ActiveQuery и добавить правила - если дилер - то andWhere().. и т.д.
б) Сделать отдельный trait и прикрепить ко всем нужным моделям и разруливать дилеров там.
в) Отдельный сервисный слой для этого? Какой (в функциональном плане)?
И самый главный вопрос:
Как бы Вы построили такую архитектуру, будь у Вас такая задача?

Заранее спасибо за советы.
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение ElisDN »

1. Через dealer_id.
2. Product::find()->forDealer($id)->..., с return $this->andFilterWhere(['dealer_id' => $id]) внутри.
3. Также, как простой магазин, только с DealerMiddleware и $request->getAttribute('dealer').
Аватара пользователя
Йож
Сообщения: 574
Зарегистрирован: 2015.08.26, 03:05

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение Йож »

Спасибо!
ElisDN писал(а): 2017.09.01, 07:19 2. Product::find()->forDealer($id)->..., с return $this->andFilterWhere(['dealer_id' => $id]) внутри.
Меня волнует вопрос, что необходимо прописать forDealer($id) во многих местах и где-то могу забыть. Возможно ли подобное прописать для всех запросов касаемо модели в одном месте? В отдельном классе, который расширяет ActiveQuery, или практика не очень хороша?
ElisDN писал(а): 2017.09.01, 07:19 3. Также, как простой магазин, только с DealerMiddleware и $request->getAttribute('dealer').
Возможно чуть подробнее описать суть вот этой прослойки? DealerMiddleware
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение ElisDN »

Йож писал(а): 2017.09.01, 07:41 В отдельном классе, который расширяет ActiveQuery, или практика не очень хороша?
Также кто-то забудет и отнаследуется от ActiveQuery вместо DealerActiveQuery. Это обнаружить тоже сложно.
Йож писал(а): 2017.09.01, 07:41 Возможно чуть подробнее описать суть вот этой прослойки? DealerMiddleware

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

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);
    }
}
Но это не для Yii.
Аватара пользователя
Йож
Сообщения: 574
Зарегистрирован: 2015.08.26, 03:05

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение Йож »

ElisDN писал(а): 2017.09.02, 18:53 Но это не для Yii.
Код достаточно понятен.. Спасибо.
Судя по invoke - объект вызывается как функция.
Подскажите самые логичные варианты вызова для Yii2?
Через поведение, трейт, beforeAction, еще как-то?
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение ElisDN »

Редирект делать в beforeRequest или beforeAction, а читать из cookies уже в контроллере (напрямую или в хелпере).
Аватара пользователя
Йож
Сообщения: 574
Зарегистрирован: 2015.08.26, 03:05

Re: Совет по архитектуре магазина с несколькими филиалами

Сообщение Йож »

ElisDN писал(а): 2017.09.03, 07:41 Редирект делать в beforeRequest или beforeAction, а читать из cookies уже в контроллере (напрямую или в хелпере).
Необходимо будет класс разнести по разным функциям? Так как в примере класса эти две задачи делаются в одной функции.. (__invoke)
В принципе же реально этот класс использовать в том в виде, какой он есть - в Yii.
Ответить