MODX отлично работает с дружественными url и представляет кучу настроек для их функционирования, а там, где настроек не хватает, он даёт нам замечательный инструмент для описания собственной логики — системные плагины по событию OnPageNotFound.
Как следует из названия, событие это возникает, когда MODX не смог найти страницу по запрошенному адресу, и в этот момент мы можем перехватить запрос и вывести что-то своё. Если же мы ничего не перехватываем, то выводится 404 not found.
Теория
За обработку запроса от пользователя отвечает класс modrequest.class.php, в котором запускается метод handleRequest(). Он определяет, каким именно образом запрашивается страница, по id или по alias?Первый случай нас не интересует, ибо это не friendly urls, а вот во втором вызывается сравнительно новый метод modX::findResource(). Именно он отвечает за сопоставление запрошенного адреса и id страницы.
Если страница найдена, то findResource возвращает её id, MODX получает нужный объект, передаёт в класс ответа
modresponse.class.php и всё хорошо. А вот если же findResource возвращает false, то вызывается метод modX::sendErrorPage().
Именно в этом методе и генерируется событие OnPageNotFound, в которое мы можем вклиниться и подсунуть нужную нам страницу.
Практика
Пишем плагинчик:<?php if ($modx->event->name != 'OnPageNotFound') {return false;} echo '<pre>'; print_r($_REQUEST); print_r($_SERVER); die;Отмечаем для него соответствующее событие, сохраняем и открываем на сайте любой несуществующий адрес, типа site.com/notfoundpage.html.
Вы должны будете увидеть вот такой вывод:

Первый массив содержит запрос пользователя, в котором должен быть ключ, указанный в системной настройке request_param_alias, а второй массив содержит переменные сервера. В принципе, они не особо нужны, но могут пригодиться для отладки.
Грамотно ловим запрошенный юзером адрес:
// Определяем системную переменную friendly urls $alias = $modx->context->getOption('request_param_alias', 'q'); // Проверяем её наличие в запросе. // Если не находим, то это фигня какая-то - выходим if (!isset($_REQUEST[$alias])) {return false;} // А если есть - работаем дальше $request = $_REQUEST[$alias]; echo $request;die;
Вот мы и получили запрошенный адрес. Собственно, главный фокус в том, чтобы опираясь на запрошенный адрес вывести нужную нам информацию.
Давайте продолжим на реальном примере.
Вывод товаров бренда
Создаём на сайте страницу /brands/ в которой может быть вызов каталога товаров или что-то подобное — сюда мы будем отправлять юзера.[[!mFilter2? &parents=`9` &hideContainers=`1` &element=`msProducts` &filters=` ms|price:number, parent:parents, msoption|tags, ms|vendor:vendors ` &class=`msProduct` &sort=`product|pagetitle:asc` &tplFilter.outer.ms|price=`tpl.mFilter2.filter.slider` &tplFilter.row.ms|price=`tpl.mFilter2.filter.number` &tpls=`tpl.msProducts.row,tpl.msProducts.row2` ]]
Затем разбрасываем на сайте ссылки типа /brands/имябренда/, или /brands/имябренда.html, или /brands/имябренда — на ваше усмотрение. Мне нравится /brands/имябренда.
Пройдя по такой ссылке юзер сгенериует событие OnPageNotFound, где его перехватит наш плагин. Проверяем:

Ну а теперь можно уже и написать рабочий плагин:
<?php if ($modx->event->name != 'OnPageNotFound') {return false;} $alias = $modx->context->getOption('request_param_alias', 'q'); if (!isset($_REQUEST[$alias])) {return false;} $request = $_REQUEST[$alias]; $tmp = explode('/', $request); // Ссылка подходит под заданный формат: brands/brandname if ($tmp[0] == 'brands' && count($tmp) >= 2) { // Определяем id раздела /brands/. // Конечно, можно его и руками прописать - но так гибче if (!$section = $modx->findResource($tmp[0] . '/')) { // Если вдруг раздел куда-то делся - выходим. return false; } // Теперь очищаем имя бренда от возможного расширения $name = str_replace('.html', '', $tmp[1]); // Если очищенное имя не равно запрошенному - то можно отредиректить юзера // Также возможен вариант с косой на конце имени бренда - его тоже учитываем // SEOшники должны оценить =) if ($tmp[1] != $name || (isset($tmp[2]) && $tmp[2] == '')) { $modx->sendRedirect($tmp[0] . '/' . $name); } // Люди с неправильной ссылкой ушли на правильную и дошли до этого момента со второго раза // Дальше проверяем наличие запрошенного бренда if ($brand = $modx->getObject('msVendor', array('name' => $name))) { // Круто, такой бренд есть, получаем его id $id = $brand->get('id'); // Осталось выставить нужные переменные в запрос, как будто юзер их сам указал // Так как это mFilter2 - выставляем выбранный бренд $_GET['ms|vendor'] = $_REQUEST['ms|vendor'] = $id; // А теперь подсовывем юзеру страницу брендов, а дальше сниппет на ней сам разберётся $modx->sendForward($section); } } // Иначе ничего не делаем и юзер получает 404 или его перехватывает другой плагин.
Как видите, весь смысл в том, чтобы разобрать запрошенное имя бренда, запихать его в запрос и показать нужную страницу, взамен виртуальной.
Вот и вся маршрутизация. У кого остались вопросы?
Источник: bezumkin.ru/sections/tips_and_tricks/2918/
0 комментариев