Сайт вебмастера

Сайт на нескольких CMS одновременно

17-01-2016Reading time ~ 3 min.Albireo Framework / CMS 9252

Необычная задача. В результате можно добиться того, чтобы какие-то страницы сайта создавались разными CMS. У меня стояла задача обеспечить одновременную работу LPF и MaxSite CMS. То есть был установлен сайт на MaxSite CMS, который замечательно работает. LPF нужно было использовать только для главной страницы и нескольких других (произвольных).

Эта статья описывает уже несуществующий Landing Page Framework (сейчас это Albireo). Ценность статьи в том, что она описывает общие алгоритмы, которые подходят для любых других php-систем.

Таким образом задача состоит в том, чтобы загружать только реально созданные LPF-страницы, во всех остальных случаях должна работать MaxSite CMS.

Как правило, такие вещи делаются «в лоб»: вторая система устанавливается в отдельный каталог сайта. Но тогда приходится мириться с дополнительным сегментом в адресе страниц. Ну и в этом способе сложно обеспечить работу главной.

Как правило CMS подключается через корневой index.php. Если сайт использует ЧПУ, то первоначальная настройка URL-запроса происходит в .htaccess. Входящий запрос обрабатывается и в «скрытом» виде подключается index.php, который уже дальше сам рулит как ему нужно.

Очевидно, что для одновременной работы нескольких CMS потребуется переименовать index.php. Например для MaxSite CMS это будет index-mso.php, а для LPF — index-lpf.php. Таким образом на сервере будут два корневых файла разных систем.

Что касается других одноименных файлов/каталогов. Очевидно, что они не должны пересекаться. Если этого добиться не получается, значит одновременная работа систем будет невозможна.

Теперь, очевидно, что нам нужен некий диспетчер, который будет выполнять подключение (через require) нужного index-файла. Диспетчер нужно разместить в новом index.php. Таким образом у нас получается:

  • index.php — диспетчер
  • index-mso.php — MaxSite CMS
  • index-lpf.php — LPF

Но у нас есть еще .htaccess в котором формируется нужный URL-запрос.

Если открыть эти файлы, то различие по сути будет только в правилах RewriteRule.

MaxSite CMS
RewriteRule ^(.*)$ /index.php/$1 [L,QSA]
 
LPF 
RewriteRule ^(.*)$ /index.php?page=$1 [QSA]

Если открыть другие CMS, то их правила будут другими. Здесь главное определить какое правило оставить (или даже переписать), чтобы обе системы нормально работали. В нашем случае должен остаться .htaccess от LPF, поскольку он формирует более сложный GET-запрос (добавляет page=...).

Дальше следует определить какие именно GET-запросы после прохождения .htaccess сформировались. Это довольно просто увидеть в php-переменной $_SERVER['QUERY_STRING'], которую можно вывести в диспетчере.

Вот именно на определенном $_SERVER['QUERY_STRING'] и должен подключаться соответствующий index-файл.

Самый простой способ прописать адреса вручную.

if (
	$_SERVER['QUERY_STRING'] == '' or
	$_SERVER['QUERY_STRING'] == 'page=hello'
	)
	require 'index-lpf.php';
else
	require 'index-mso.php';

В данном примере главная страница и /hello отдаст LPF, а все остальные страницы — MaxSite CMS. Обратите внимание, что GET-запрос от LPF формируется с page=, поскольку так работает .htaccess.

Мне хотелось, чтобы LPF отдавал все свои страницы. Поскольку страницы в LPF — это каталоги в lpf-content/pages/, то достаточно автоматом их получить и после проверять на вхождение в get-запрос.

Привожу готовый рабочий код index.php (диспетчер).

<?php
$lpf_pages = _directory_map(dirname(realpath(__FILE__)) . '/lpf-content/pages/', 1);
$lpf_pages = array_map('_add_route', $lpf_pages);
 
if (
	$_SERVER['QUERY_STRING'] == '' or // главная идет от LPF 
	in_array($_SERVER['QUERY_STRING'], $lpf_pages)
	)
	require 'index-lpf.php';
else
	require 'index-mso.php';
 
 
function _add_route($s)
{
	return 'page=' . $s;
}
 
function _directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)
{
	if ($fp = @opendir($source_dir))
	{
		$filedata	= array();
		$new_depth	= $directory_depth - 1;
		$source_dir	= rtrim($source_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
 
		while (FALSE !== ($file = readdir($fp)))
		{
			if (!trim($file, '.') OR ($hidden == FALSE && $file[0] == '.')) continue;
 
			if (($directory_depth < 1 OR $new_depth > 0) && @is_dir($source_dir.$file))
				$filedata[$file] = _directory_map($source_dir . $file . DIRECTORY_SEPARATOR, $new_depth, $hidden);
			else
				$filedata[] = $file;
		}
 
		closedir($fp);
		return $filedata;
	}
 
	return FALSE;
}
 
# end of flie

Функция _directory_map — это хелпер из CodeIgniter. Функция _add_route добавляет к имени каталога page=, чтобы уже без ухищрений использовать в условии in_array.

Данный подход универсальный к любым CMS, главное подобрать get-запрос в .htaccess, который будет работать на этих системах.

Related Posts