Переключение контекстов в зависимости от URL
Периодически появляется задача — создать несколько контекстов и сделать так, чтобы нужный загружался для работы автоматически в зависимости от URL. Будем считать, что ЧПУ настроены. Более никаких изменений ни в .htaccess, ни в конфигах сервера. Ведь часто встречаются злые хостеры, которые не позволяют этого делать. А еще нежелательно создавать подкаталоги и копировать в них index.php, иначе после каждого обновления придется следить за его изменением.
Мы будем переключать контексты с помощью плагина на событие OnHandleRequest.
Есть 2 основных вида URL, которые надо обрабатывать:
-
context.site.ru
-
site.ru/context/
Поскольку между этими вариантами отличаются только плагин и три настройки контекстов, предварительно опишем общие действия:
-
Создать субдомен его направить на тот же каталог, где лежит основной сайт ИЛИ создать алиас для основного домена;
-
Создать контекст и следующие его настройки:
-
error_page = ID страницы для 404 ошибки в данном контексте
-
site_name = Название сайта для этого контекста
-
site_start = ID главной страницы в данном контексте
-
-
Создаем плагин с любым именем (например, swCtx), отмечаем галкой событие onHandleRequest.
Первый вариант очень простой, плагин имеет всего несколько строк.
Для соответствующего контекста создаем следующие настройки:
-
base_url = /
-
http_host = context.site.ru
-
site_url = http://context.site.ru/
В нашем плагине пишем следующий код:
<?php
if ($modx->event->name == 'OnHandleRequest') {
if ($modx->context->get('key') == 'mgr') {return;}
// сравнение текущего имени хоста и искомого
if (strstr($_SERVER['HTTP_HOST'], 'testen.a.aaa0.ru') != false) {
$modx->switchContext('endomain');
return;
}
}
Для первого случая больше ничего делать не надо. Если контекстов на субдомены несколько, просто скопируйте нужное количество раз блок
if (strstr($_SERVER['HTTP_HOST'], 'context.site.ru') != false) {
$modx->switchContext('context');
return;
}
, заменив в нем название контекста и субдомена.
Больше ничего.
Со вторым вариантом чуть сложнее. Дело в том, что кроме переключения контекста необходимо дополнительно отправить пользователя через $modx->sendRedirect() на запрашиваемую страницу. А для этого ее надо еще и найти.
Настройки контекста:
-
base_url = /ctxfolder/
-
http_host = site.ru
-
site_url = http://site.ru/ctxfolder/
В коде плагина комментарии позволяют понять всю его логику, дополнительно описывать не будем.
<?php
if ($modx->event->name == 'OnHandleRequest') {
if ($modx->context->get('key') == 'mgr') {return;}
// получение первого каталога из URI
preg_match('/^(\/[a-z0-9_-]*\/)/i', $_SERVER['REQUEST_URI'], $matches);
$key = $matches[0];
// сопоставление полученного названия каталога и пути для контекста
switch ($key) {
case '/ctxfolder/' :
$modx->switchContext('ctxfolder');
$context = 'ctxfolder';
// получение URI страницы относительно контекста
$uri = preg_replace('/^\/ctxfolder\//i', '', $_SERVER['REQUEST_URI']);
break;
}
if ($uri != '') {
// если URI не пуст, ищем страницу в нужном контексте
$res = $modx->getObject('modResource', array('context_key' => $context, 'uri' => $uri));
// если страница существует, отправляем на нее. Если нет, вызываем 404
if ($res) $modx->sendForward($res->get('id'));
else $modx->sendErrorPage();
}
// если URI пуст, отправляем на стартовую страницу контекста
else $modx->sendForward($modx->getOption('site_start'));
}
В таком виде все должно работать. Здесь не учитывается 403 ошибка, тк я, честно говоря, до сих пор не понял логику MODX в ее случае, ведь вместо нее создается видимость отсутствия ресурса, и соответственно выдается 404.
Возможно, приведенный код не является оптимальным. Но он отвечает на вопрос: как переключить контекст в зависимости от URL. И если в случае с субдоменом решений в интернете достаточно, то для второго случая без изменения исходников я видел только черновик в комментариях Василия.
P.S.: буду рад, если Василий напишет свои комментарии для улучшения этого мануала.
Обновлено
Плагин Василия для второго случая, когда контекст в субкаталоге, лаконичнее и правильнее:
<?php
if ($modx->context->key == 'mgr') {return;}
elseif ($modx->event->name == 'OnHandleRequest') {
$var = $modx->getOption('request_param_alias', null, 'q');
$request = $_REQUEST[$var];
if (strpos($request, 'context/') === 0) {
$modx->switchContext('context');
$_REQUEST[$var] = substr($request, 8);
}
}
0
👍
👎
❤️
🔥
😮
😢
😀
😡
6 205
17.10.2013, 12:35:25
8 комментариев
Василий Наумкин
17.10.2013, 16:39:01
У меня на дев-сайте второй контекст называется "context". Использую вот такой плагин:
Воеводский Михаил
18.10.2013, 02:41:06
Предполагал такое решение, но не додумал.
Спасибо.
Воеводский Михаил
18.10.2013, 02:44:31
Василий, а это баг или нет, что после редактирования пост снова попадает в "Вопросы"?
Василий Наумкин
18.10.2013, 10:52:50
Это недоработка Tickets.
У тебя же нет права публиковать в другой блог, а компонент не умеет в таких случаях оставлять уже имеющийся parent. Вот и перекидывает куда можно.
Sergey Sinicin
22.01.2014, 05:13:11
Был старый сайт на html. где ссылки: домен.ру/о нас.html- о нас русский домен.ру/эбаут ас.htmlо нас английский Перенес все на модх, создал русский и английский контексты. Установил бабел. А дальше потребовалось настроить так, что бы ссылки остались теми же.
Можно ли сделать так? ..... $var = $modx->getOption('request_param_alias', null, 'q'); $request = $_REQUEST[$var]; //далее команды пока не знаю модх-найти документ по урл $request ид контекста = модх-определить ид контекста по документу $modx->switchContext(ид контекста);
как-то так... все только для того чтобы сохранить старые ссылки.
Василий Наумкин
22.01.2014, 12:24:51
Просто пропиши вручную нужные uri - Revolution это позволяет
Для поиска ресрсов по uri есть метод modX::findResource().
Sergey Sinicin
22.01.2014, 14:44:47
Спасибо, Василий за наводку. При стандартном htaccess, вот такой плагин переключателя языков получился:
Не знаю на сколько это правильно ...
Sergey Sinicin
22.01.2014, 15:05:33
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.