MODX. Контексты, мультисайтовость и многоязычность в MODX

В MODX контексты — это своего рода группы, создающиеся для файлов. Каждая группа отвечает за какую-то свою область. По умолчанию, в новой установке MODX, уже создано 2 контекста: контекст mgr набор файлов реализующий админпанель MODX; и контекст web — набор файлов для публичной части сайта.

Чаще всего дополнительные контексты создаются для реализации мультиязычных и многосайтовых проектов. 

Схема создания дополнительных контекстов:

  1. Идем в системное меню, пункт «Контексты» (Contexts);
  2. Нажимаем «создать новый», и заполняем поля
    • Ключ — обозначение контекста латиницей, например eng;
    • Имя — полное имя контекста, например English;
    • Описание —  краткое описание назнаения контекста;
    • Сортировка — индекс важности контекста (на каком месте он будет в общем списке контекстов).
  3. Сохраняем данные нового контекста;

При создании мультисайтовости есть 2 основных типа ссылок: eng.site.com и site.com/eng/. Порядок действий настройки контекста для обоих случаев похож, отличия лишь в значении параметров и плагине, который обрабатывает переключение контекстов. 

  1. В списке контекстов нажимаем правой кнопкой мыши на контекст который надо отредактировать, выбираем редактировать;
  2. В открывшейся странице есть несколько вкладок:
    • Общая информация — информация которую мы заполнили при создании контекста;
    • Настройки контекста — в ней создаются дополнительные параметры для контекста. Каждый контекст может иметь свои собственные настройки, которые переопределяют или расширяют системные настройки. Контекстные настройки, в свою очередь, могут быть переопределены или расширены пользовательскими настройками. Иерархия настроек: настройка системы → настройка контекста → настройка пользователя;
    • Права доступа — вкладка для настройки ограничения прав доступа.
  3. В настройках контекста добавляем новые параметры, базовый набор:
    • base_url — базовый путь до файлов:
      • eng.site.com — «/»;
      • site.com/eng/ — «/eng/»;
    • site_url — адрес для сайта, со слешем на конце;
      • eng.site.com — «eng.site.com/»;
      • site.com/eng/ — «/eng/»;
    • site_start — стартовая страница сайта.
    • cultureKey — для многоязычных сайтов, указание индекса языка.
  4. Создаем плагин на событие onHandleRequest, для переключения между контекстами. Универсального плагина порекомендовать не могу, поскольку на переключение контекстов влияет много факторов, вплоть до включенных friendly urls, но в конце статьи есть список ссылок на плагины для разных случаев. Так же можете посмотреть на компоненты contexRouter и X-Routing.
  5. При отладке настроек контекста убедитесь, что нужные группы пользователей имеют к нему доступ.

После того как новый контекст создан, его можно увидеть в дереве ресурсов. Он выглядит как отдельный каталог первого уровня, с соответствующей иконкой (на момент написания статьи — иконка планеты). Ресурсы в него добавляются тем же путем что и в контекст web. Ресурсы можно спокойно перетаскивать из одного контекста в другой.

// Получаем настройки контекста
$setting = $modx->getOption('my_context_setting');

Для распределения контекстов в параметрах сниппетов можно использовать чанки:

// вызов сниппета
{'!pdoPage' | snippet : [
            'ajaxMode' => 'default',
            'parents' => 'ctxArticChoise',
            'tpl' => 'tpl.item',
            'limit' => 16,
]}

// fenom код для чанка ctxArticChoise
{if $modx->context->get('key') == 'eng'}
15
{else}
1
{/if}

// или тег MODX с модификаторами
[[*context_key:is=`eng`:then=`15`:else=`1`]]

Для использования соответствующих лексических значений в шаблоне можно использовать следующую запись:

[[%lexicon_key? &namespace=`site` &language=`[[++cultureKey]]`]]

Для настройки pdoSitemap используется параметр context:

{'pdoSitemap' | snippet : ['context' => 'eng']}

Подключение чанков:

// теги MODX
[[$chunkprefix_[[++cultureKey]]]]

// Fenom из базы
{include ('chunkprefix_' ~ $_modx->config.cultureKey)}

// Fenom из корня
{include ('file:chunks/chunkprefix_' ~ $_modx->config.cultureKey ~ '.tpl')}

Плагин для 2 типа ссылок (site.com/eng/) при включенном friendly urls (от Василия Наумкина):

<?php
// Работаем только на фронтенде и только с friendly urls
if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr' || !$modx->getOption('friendly_urls')) {return;}

// Получаем запрашиваемый url
$alias = $modx->getOption('request_param_alias', null, 'alias', true);
$request = &$_REQUEST[$alias];

// Выбираем контексты с настройкой base_url
$q = $modx->newQuery('modContextSetting', array('key' => 'base_url', 'value:!=' => ''));
$q->select('context_key,value');

$contexts = array();
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
	// Учитываем наш запрос в БД
	$modx->queryTime += microtime(true) - $tstart;
	$modx->executedQueries++;
	// Разбираем результаты
	while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
		$base_url = trim($row['value'], '/');
		$context = $row['context_key'];
		// Если запрос начинается с base_url какого-то контекста
		if (preg_match('/^('.$base_url.')\//i', $request)) {
			// То переключаемся на этот контекст
			// Web инициализируется в index.php - на него переключаться не нужно
			if ($context != 'web') {
				$modx->switchContext($context);
			}
			// Вырезаем base_url из запроса, чтобы MODX нашел ресурс по uri
			$request = preg_replace('/^'.$base_url.'\//', '', $request);
			// Дело сделано - выходим из цикла
			break;
		}
	}
}

Ссылки на статьи с плагинами:

Возможные проблемы 

  • При возникновении проблемы с доступом к папке /assets в случае 2 типа адреса (site.com/eng/) можно использовать следующий код для .htaccess: 
    # redirect all requests from /lang/assets* to /assets*
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(ru|eng)/assets(.*)$ assets$2 [L,QSA]
  • Если при использовании 1 типа адреса (eng.site.com) возникает проблема с путями в ссылках и путями до папки assets, при которой как бут-то бы не работает директива use_alias_path, перепроверьте запись site_url в настройках контекста. Она должна быть указана вместе с протоколом и слешем на конце: https://eng.site.com/