Exebeche
@Exebeche
Осваиваю программирование

Как настроить ЧПУ для разных экшенов одного контроллера в YII2?

Имеется магазин с контроллером "Каталог" в котором есть экшены: категории, товары...
Категории стоят на nested sets, а товары - как товары...
Есть правило для категорий и ЧПУ у них отлично работает, пока у товаров id вместо slug. Как только и товарам пытаюсь ЧПУ приделать начинается ерунда - или товары открываются как 404, или и категории и товары открываются как 400.
Так понимаю, что нужно отдельному экшену написать отдельное правило, но не нашел как к <_a:product> добавить условие со slug:[\w\-]+
Как его победить? Если можно подробнее объясните, а то читать-то я читал, только - ыть.

На всякий правила в urlManager:
'catalog' => 'shop/catalog/index',
// 'catalog/<url:[\w\-]+>' => 'shop/catalog/product',
[class' => 'frontend\urls\CategoryUrlRule'],


и в правилах для категорий:
public function parseRequest($manager, $request)
    {
        if (preg_match('#^' . $this->prefix . '/(.*[a-z])$#is', $request->pathInfo, $matches)) {
            $path = $matches['1'];

            $result = $this->cache->getOrSet(['category_route', 'path' => $path], function () use ($path) {
                if (!$category = $this->repository->findBySlug($this->getPathSlug($path))) {
                    return ['id' => null, 'path' => null];
                }
                return ['id' => $category->id, 'path' => $this->getCategoryPath($category)];
            }, null, new TagDependency(['tags' => ['categories']]));

            if (empty($result['id'])) {
                return false;
            }

            if ($path != $result['path']) {
                throw new UrlNormalizerRedirectException(['shop/catalog/category', 'id' => $result['id']], 301);
            }

            return ['shop/catalog/category', ['id' => $result['id']]];
        }
        return false;
    }

    public function createUrl($manager, $route, $params)
    {
        if ($route == 'shop/catalog/category') {
            if (empty($params['id'])) {
                throw new InvalidParamException('Empty id.');
            }
            $id = $params['id'];

            $url = $this->cache->getOrSet(['category_route', 'id' => $id], function () use ($id) {
                if (!$category = $this->repository->find($id)) {
                    return null;
                }
                return $this->getCategoryPath($category);
            }, null, new TagDependency(['tags' => ['categories']]));

            if (!$url) {
                throw new InvalidParamException('Undefined id.');
            }

            $url = $this->prefix . '/' . $url;
            unset($params['id']);
            if (!empty($params) && ($query = http_build_query($params)) !== '') {
                $url .= '?' . $query;
            }

            return $url;
        }
        return false;
    }

    private function getPathSlug($path): string
    {
        $chunks = explode('/', $path);
        return end($chunks);
    }

    private function getCategoryPath(Category $category): string
    {
        $chunks = ArrayHelper::getColumn($category->getParents()->andWhere(['>', 'depth', 0])->all(), 'slug');
        $chunks[] = $category->slug;
        return implode('/', $chunks);
    }
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
Exebeche
@Exebeche Автор вопроса
Осваиваю программирование
На самом деле все оказалось смешнее некуда.
Изначально я правильно задал правило маршрутизации для товаров - 'catalog/<url:[\w\-]+>' => 'shop/catalog/product', просто в модели метод find нужно было задать по slug вместо id как было изначально.
И все стало чудЭсно работать))
Всем спасибо за помощь.
Осталось осилить как теперь 301 сделать со старых адресов
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы