Adding Rules Dynamically

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
i1-home
Сообщения: 4
Зарегистрирован: 2017.08.18, 13:12

Adding Rules Dynamically

Сообщение i1-home »

Добрый день.

Вопрос в задании паттернов.

Реализация:
К примеру есть несколько страниц и их роуты
1) /computer
2) /computer/motherboard
3) /computer/keyboard

В бутстрапе в цикле я добавляю правила
$app
->getUrlManager()
->addRules(
[
[
'pattern' => $page['route'],
'route' => "product/category"
]
],
false
);

на странице /computer класс Sort в составе dataProvider'a создает ссылку /computer/motherboard?sort=price а не /computer?sort=price (как должно быть)

Подскажите плиз как правильно сформулировать pattern, заранее спасибо!
Аватара пользователя
futbolim
Сообщения: 2051
Зарегистрирован: 2012.07.08, 19:28

Re: Adding Rules Dynamically

Сообщение futbolim »

Попробуйте у формы action прописать
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Adding Rules Dynamically

Сообщение Nex-Otaku »

Маршрутизатор смотрит маршруты "product/category" и берёт первый попавшийся, а они у вас все к одному и тому же маршруту привязаны. Поэтому и получается путаница - ведь он не знает, как их различать.

Если у вас категории не вложенные, и имеют лишь один уровень, можно сделать так.

1. Завести два маршрута с параметрами, цикл в бутстрапе убрать.

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

'<product:[0-9a-zA-Z\-]+>/<category:[0-9a-zA-Z\-]+>' => 'product/category',
'<product:[0-9a-zA-Z\-]+>' => 'product/category',
Обращаю внимание, что порядок важен! Чтобы всё правильно решалось, сначала должен идти самый специфичный маршрут, потом более общий.

2. При создании ссылки указывать соответствующие параметры.

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

Url:to(['product/category', 'product' => 'computer'])
Url:to(['product/category', 'product' => 'computer', 'category' => 'motherboard'])
Теперь эти маршруты для самого маршрутизатора будут различаться, потому что помимо строки контроллер-действие "product/category", он ещё будет хранить параметры, и по ним построит уже всё правильно.
i1-home
Сообщения: 4
Зарегистрирован: 2017.08.18, 13:12

Re: Adding Rules Dynamically

Сообщение i1-home »

Про первый попавшийся, я понял, а нельзя задать что бы он смотрел на всю строку целиком а не на часть "/computer"
Есть же к примеру в регулярке ^строка$ - такое правило от начала строки и до конца что бы сравнивал, но я так пробовал не сработало...
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Adding Rules Dynamically

Сообщение Nex-Otaku »

Так он и смотрит. Регулярка здесь не поможет, проблема не в ней. Просто ты не понимаешь, как оно работает.

Смотри как получается.

Твой пример с циклом.

Вот у тебя три правила, по первому примеру с циклом.

URL "/computer" соответствует маршруту "product/category"
URL "/computer/motherboard" соответствует маршруту "product/category"
URL "/computer/keyboard" соответствует маршруту "product/category"

Все они привязаны к одному маршруту.

Поэтому при разборе URL, всё корректно определяется - по первому совпавшему URL мы определяем маршрут "product/category", который нам и нужен.

Далее, что происходит при генерации ссылки на сортировку во вьюшке?

Весь процесс идёт в обратном порядке.

1. Берётся текущий маршрут - "product/category".

2. Для него ищется подходящее правило для генерации URL.

3. Но для маршрута "product/category" уже существует три равнозначных правила, с точки зрения маршрутизатора. Они все указывают на тот же маршрут. Поэтому он и выбирает любое из них, первое попавшееся.

Маршрутизатор при генерации URL различает правила по конечным маршрутам и параметрам. Конечный маршрут у тебя одинаковый, а параметров нет. Поэтому и различий между правилами нет.

Мой пример с параметрами.


Есть два правила.

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

'<product:[0-9a-zA-Z\-]+>/<category:[0-9a-zA-Z\-]+>' => 'product/category',
'<product:[0-9a-zA-Z\-]+>' => 'product/category',
Помимо самого URL, указаны параметры.

При разборе URL, маршрутизатор будет хранить не только текущий маршрут 'product/category', но и значения параметров - какой выбран продукт и какая выбрана категория для текущей страницы.

Поэтому, для генерации URL он обратно его построит корректно - "ага, сейчас выбран маршрут "product/category", значит в шаблон "<product:[0-9a-zA-Z\-]+>/<category:[0-9a-zA-Z\-]+>" подставляем значение параметра "product"="computer", значение параметра "category"="keyboard", получим "/computer/keyboard", вуаля!"
i1-home
Сообщения: 4
Зарегистрирован: 2017.08.18, 13:12

Re: Adding Rules Dynamically

Сообщение i1-home »

Я вас понял, спасибо за разъяснения.

Но это не раешает задачи)

Дело в том что структура которую я привел ранее
1) /computer
2) /computer/motherboard
3) /computer/keyboard

Может отличаться
к примеру добавиться 3 уровень
3) /computer/keyboard/logitech

или добавиться 4 страница (статическая страница, а не страница каталога)
4) /contacts

все это, менеджер в любой момент может поменять (вложенность, slug - из за которого измениться роут страницы, и др)

но при этом у страницы есть "модуль" - по которому мы определяем что это "старическая страница" или "страница каталога" и можем задать роут в rules urlManger

так вот, может быть есть возможность передать "/computer/keyboard/logitech" как параметр?

Поскольку так это рабоать не будет:
'<product:[0-9a-zA-Z\-]+>' => 'product/category',
'<page:[0-9a-zA-Z\-]+>' => 'page/view

Заранее спасибо)
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Adding Rules Dynamically

Сообщение Nex-Otaku »

Пишите свой класс для правила в таком случае. Не так уж это и сложно, я делал )
i1-home
Сообщения: 4
Зарегистрирован: 2017.08.18, 13:12

Re: Adding Rules Dynamically

Сообщение i1-home »

Спасибо в любом случае)
Сделал так

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

$slugs = explode('/', $page['route']);
unset($slugs[0]);
$patternSlugs = [];
foreach ($slugs as $key => $slug) {
    $patternSlugs[] = "<{$key}:{$slug}>";
}
$rules = [
    [
        'pattern' => implode('/', $patternSlugs),
        'route' => "product/category"
    ]
];
                    
Ответить