Screamie
@Screamie
Full-stack разработчик

YII2 Как создать гибкую модульную архитектуру?

Всем привет! Разрабатываю проект на YII2 и нужна ваша помощь в понимании архитектуры модулей и маршрутизации.

Есть Yii2-Advanced приложение. В нем я хотел бы реализовать модульную структуру, что бы можно было урезать и расширять функционал (собственно этого все хотят). Нужно сделать сайт, с кучей однотипных страниц и страниц, на которых будет размещен дополнительный функционал.

Допустим у нас есть модуль Pages который отвечает, за работу со всеми страницами на сайте. Он формирует древо страниц и их URL-ы (в зависимости от вложенности и alias-ов которые придумал админ), и подключает к ним шаблоны и контент. И допустим в панели администратора мы создаем следующую структуру страниц:

  • Главная (alias: /home)
  • О компании (alias: /about)
  • Новости (alias: /news)
  • Контакты (alias: /contact)


В БД в таблице Page у нас появляются 4 записи

id | alias | name
---------------------------------
1 | /home | Главная
2 | /about | О компании
3 | /news | Новости
4 | /contact | Контакты

Пока страниц всего 4 можно сделать отдельные action в SiteController, но представим, что у нас много страниц и этот вариант не подходит.

Создаем PageController и изменяем маршрутизатор так, что бы он сначала искал страницы в БД по нашему alias и если нашел страницу с таким URL то отсылал на PageController::actionPage(), где бы мы доставали нужную страницу из базы, определяли ее шаблон, вставляли контент и выводили все это дело на фронт. А если нет, то искал controller/action в зависимости от URL-rules и выполнял его логику.

Но на странице Новости у нас должен работать модуль новостей, которые хранятся в отдельной таблице news, т.к. их может быть не одна сотня или этого модуля может не быть вообще. И у модуля news есть свой контроллер, который обеспечивает сортировку новостей по тегам, датам и любой другой функционал. К примеру NewsController::actionFindByTag() или NewsController::actionMostPopular().

И вот тут у меня возникает головная боль с маршрутами. Можно зашить дополнительное поле action, в таблицу template, которая отвечает за шаблоны страниц и чекать URL по нему. То есть если у страницы есть шаблон и его action != null
тогда уходим НЕ на PageController::actionPage(), а подставляем значение action и уходим по нему.

Теперь вроде все в порядке, пользователь набирает в адресе sitename.ru/news мы ищем эту страницу в БД, находим у нее template.action который равен news/index и уходим на NewsController::actionIndex(). И вот тут и таится проблема. Если админ изменит alias страницы Новости, например на /events, то по запросу sitename.ru/events он все равно попадет
на NewsController::actionIndex(), что нам и надо, но вот если он на странице новостей кликнет на "Показать популярные", которая должна вести на NewsController::actionMostPopular(), то единственный способ это указать контроллер и action напрямую, как news/most-popular. Соответственно происходит необоснованное изменение адресов с /events на /news/most-popular.

Резюмируя этот огромный вопрос. Не могу понять, как организовать модули с их логикой, рядом с обычными страницами без логики, и при этом что бы в панели администратора Админ мог изменять alias-ы страниц, их вложенность и прочее. Но функционал модулей сохранялся бы.

Заранее спасибо!

UPD:
Пока сошлись на том, что нужно определять принадлежность модуля к странице и как-то парсить URL в UrlManager::ParseRequest().

Хочу выразить огромное спасибо Дмитрию Елисееву, за помощь, он предложил следующий вариант парсинга URL:


В parseRequest:

- Ищем /city/events/most-popular. Не нашлось.
- Ищем /city/events. Нашлось. Тип "news". Запускаем рекурсию:

$r = clone $request;
$r->setPathInfo('news/most-popular');
return $manager->parseRequest($r);


Пока не знаю подойдет ли этот метод, но буду пробовать его. Отпишусь здесь, когда проверю. Если у кого-то есть идеи, то буду очень признателен, за помощь.
  • Вопрос задан
  • 1091 просмотр
Пригласить эксперта
Ответы на вопрос 2
qonand
@qonand
Software Engineer
Вы по моему не совсем правильно разделили Вашу систему на модули: Главная, О компании, Контакты - это обычные страницы сайта тут вопросов нет, но новости это не просто страницы - это отдельный модуль который может иметь свой специфический функционал - поиск, теги, лайки и т.п. Соответственно я бы Вам рекомендовал разделить эту задачу на два модуля:
1. Модуль статического контента - который будет содержать информационные страницы сайта, такие как "о компании", "контакты" и т.п.
2. Модуль новостей - содержащий собственно все новости
Ответ написан
@RustemS
Делай модуль в нем ещё sub модуль и будет тебе щастье
В urlManager пропиши 'enableStrictParsing' => true и укажи все явные пути.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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