Как я сделал роутинг для e-commerce проекта на Yii2

в 2:50, , рубрики: Песочница, метки: , , ,

Приветствую!

После нескольких лет чтения Хабра появился интерес написать и самому небольшой очерк.

Мой текст носит, скорее, самообразовательный характер. Я был бы рад дельным замечаниям и мудрым советам, так как в компании, где я проработал 2 с небольшим месяца остался один в качестве “команды разработчиков” (и такое бывает). Тимлид ушел. Наставлять на пусть истинный, как говорится, больше некому. Вот и решил выставить на ваш суд собственную реализацию роутинга для e-commerce проекта на Yii2.

Давайте представим себе условный интернет-магазин domain.zone, который может содержать товары, категории и статические страницы с одинаковой структурой url. Например:

  • domain.zone/bridgestone-blizzak-ws-60-195-55r16-91r — страница продукта;
  • domain.zone/category-slug — категория;
  • domain.zone/article-slug — статическая страница.

На самом деле имеется еще много всяких плюшек с такой же структурой url, но давайте остановимся на этих как основных.

Начнем, пожалуй, с товаров. Опустим тонкости генерации замечатального url-alias'a «bridgestone-blizzak-ws-60-195-55r16-91r». Предположим, вся строка хранится в поле «slug» в таблице/документе товаров. Было решено явно проверять, что это именно «слуг» продукта, а не, скажем, статическая страница. Мучить БД многочисленными запросами — явно плохая идея. Поэтому использовал индекс elasticsearch. Почему не sphinx и т.п. — это тема отдельной статьи. Не будем останавливаться на выборе технологии здесь.

Итак, было создано соответствующее правило ProductUrlRule. Реализация примерно следующая:

 public function parseRequest($manager, $request)
    {
        $slug = $request->getPathInfo();

        if (!$slug) {
            return false;
        }

        if (strpos($slug, "/")) {
            return false;
        }

        $queryBuilder = (new frontendcomponentsElasticQueryBuilder())
            ->setIndex('indexName')
            ->setType('indexType')
            ->setQueryStringQuery('slug', $slug, 'and');

        $loader = (new frontendcomponentsDataLoader($queryBuilder))->load();

        if ($loader->getTotal() === 0) {
            return false;
        }

        return [$this->route, ['slug' => $slug]];
    }

По такому же принципу добавлены правила для категорий и статических страниц.

Такой путь показался мне самым оптимальным. Хотелось бы, конечно, обойтись исключительно правилами роутинга, без дополнительных запросов, пускай даже к индексу, но этого добиться я так и не смог.

Буду благодарен за полезные советы.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js