Сайт на нескольких 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
, который будет работать на этих системах.