Добрый день.
В этой статье я постараюсь вкратце описать архитектуру нового форумного движка XenForo, нового конкурента VBulletin и IPB, насколько это у меня получится после пары часов знакомства с исходником. О XenForo, спроектированном бывшими авторами VBulletin3, Киром и Майком, я уже немного писал.

Размер основной части кода XenForo 3,24 МБ (3 405 312 байт). Еще 8,31 МБ (8 724 429 байт) занимает Zend Framework, который поставляется вместе с кодом XenForo.
XenForo полностью основан на MVC архитектуре. Есть отдельные классы для моделей, видов и контроллеров. Корневой index.php имеет размер в 467 байт и заканчивается, как и положено в таких случаях
Разумеется, в ходу автозагрузчик классов. Система именования классов как в ZF.
Сама MVC пока внутри использует классы Zend, но то, что XenForo_Controller не унаследован от соответствующих классов ZF, говорит о том, что эта часть будет переписана.
Все контроллеры унаследованы примерно одинаково: class XenForo_ControllerPublic_Forum extends XenForo_ControllerPublic_Abstract. После Symfony с ее actions такой подход несколько непривычен, но к нему быстро привыкаешь.
Система роутинга спроектирована расширяемой. Расширение происходит через привязку префиксов URL к классам-обработчикам. SEO из коробки, разумеется. Никаких плагинов не требуется.
Архитектура XenForo закладывалась надолго :) Во всяком случае, в первый раз в форумном движке я встретил более-менее внятную архитектуру контента, слегка напоминающую Drupal («Everything is a node», помните?). Пока в XenForo типов контента четыре: категория, раздел форума, страница и ссылка (обычный редирект). Каждый тоже называется Node. Причем, каждый экземпляр узла может быть предком/потомком экземпляра другого типа. Пока не знаю, как эта гремучая смесь, например, из страницы и дочернего ей раздела форума, будет отображаться, не пробовал :). Причем, некоторые типы контента можно слегка расширять прямо из коробки. Так, например, для страницы помимо, собственно, ее HTML содержимого можно указать PHP обработчик, который получит из БД дополнительные данные, изменит д��зайн страницы, вставит в нее информацию или вообще плюнет в пользователя ошибкой. PHP обработчики везде указываются не кодом на PHP, как этого можно было ожидать, а именами класса и метода. При активации хука класс будет загружен автолоадером (соответственно, должен быть правильно расположен в файловой системе).
Типы контента пока заданы жестко, самому добавить их не получится. Даже их названия в админке почему-то не локализованы.
XenForo использует Sabre и Zend Framework. Причем, наличие в коде мест, подобных
скорее всего, означает, что от лишних зависимостей на протяжении разработки продолжат избавляться, заменяя их на что-то свое более легковесное и более специализированное.
Из ZF используется совсем немного классов. В их числе Zend_Registry (в качестве реестра для синглтон-подобных объектов вроде экземпляра XenForo_Db), Zend_Config, Zend_Cache (много чего кеширует, в частности используется в базовом классе моделей XenForo_Model), Zend_Service_ReCaptcha, Zend_Http_Client, Zend_Mail, Zend_Validate и некоторые другие.
Для работы с базой данных используется часть бандла Zend_DB (Zend_Db_Adapater_Abstract и Ко), завернутая в классе XenForo_DB, что опять говорит о том, что и эту часть в последствии перепишут.
Конструктор запросов не используется, они встроены прямо в код, как обычно (что, конечно, несколько затруднит поддержку нескольких баз данных. Но с другой стороны, запросы сконцентрированы внутри модели, так что...)
Для расширения форума предназначено несколько событий, на которые можно повесить обработчики. Обработчики указываются, как уже было сказано, через имя класса и метода, что позволяет использовать акселераторы вроде APC для кеширования аддонов. Список обработчиков вместе с базовой информацией о плагине помещается в *.xml файл. Писать его руками не обязательно. Достаточно активировать отладочный режим на форуме и в админке появятся дополнительные возможности. PHP файлы аддона, разумеется, надо будет сначала распаковать в соответствующую папку. Классы XenForo лежат в /library/XenForo, стало быть ваши будут лежать в /library/VasyaCorp. Меня это порадовало, поскольку довольно часто я занимался поиском остатков плагина в файловой системе при его удалении из VBulletin.
Поскольку практически каждый аддон должен иметь настройки, их можно создавать прямо в админке и экспортировать в *.xml плагина вместе с информацией о хуках. Располагаются они там же, где и настройки самого XenForo. Встраивать их можно в произвольные места раздела общих настроек XenForo. Устроено все примерно также, как это было в VBulletin. Очень удобно и практически нет необходимости писать код для их поддержки.
Меня немного удивило количество хуков. Я полагаю, все помнят оглушительное количество хуков в VBulletin, которое даже в голове нельзя было удержать? В XenForo хуков всего… 17! Такое количество объясняется их назначением. Вот их имена:
Небольшая инспекция кода показала, что семейство хуков load_class_* предназначено для динамического расширения системы классов XenForo. Вот ключевой кусочек кода:
А несколько неожиданное для меня использование хука visitor_setup для изменения всего чего угодно на странице показано тут. Практически через любой хук вы можете залезть в сердце системыи наделать делов.
В общем, малое число хуков, похоже, вполне себе компенсируется их мощью.
Как и во всех современных форумах в XenForo есть КУЧА шаблонов. Синтаксис довольно мощный (см. отрывки внизу), впрочем, этим уже никого не удивишь. Спецтеги пишутся как в PHPTAL («неймспейсированный» XML/HTML). Один шаблон может содержать несколько файлов. Например, шаблон forum_list содержит forum_list, node_list (он вставляется в forum_list), node_list.css, sidebar.css, sidebar_online_users. CSS в шаблоне подключается через xen:require, что позволяет кешировать все CSS файлы как угодно.
Обратите внимание на использование хелперов в шаблонах. Хелпер, как и в Symfony, это просто метод класса. Например, вот код хелпера helperUserLink:
Поисковая машина в XenForo реализована в виде отдельного класса (в отличие от ненавидимой мною реализации в VB, в которой, по-моему, сами разработчики давно уже запутались, просто не сознаются в этом), унаследованного от XenForo_Search_SourceHandler_Abstract. В настоящий момент реализация только одна — MySqlFt.php (class XenForo_Search_SourceHandler_MySqlFt extends XenForo_Search_SourceHandler_Abstract), но в ближайшее время должен появится Sphinx. Мода такая нынче :) Форумы уже не те, что раньше. Растут, как на дрожжах…
В админке пока нет опции для активации другого поискового движка, но не надо забывать, что это все же Beta.
Система локализации практически полностью повторяет свой аналог из VBulletin с тем исключением, что фразовые группы отсутствуют вообще. Вот начало файла фраз английского языка:
Каждый аддон может иметь собственные фразы. Языки можно экспортировать. Переводить аддоны можно прямо в админке.
Кстати, русская локализация XenForo уже почти готова.
Я не дизайнер и вообще у меня плохой вкус. Все, что касается дизайна и его разработки меня пугает. Но в XenForo мы видим древовидную систему стилей, аналогичную VB, в которой мы можем взять какой-то стиль за основу и изменить часть его настроек или шаблонов. Только Кир с Майком реализовали самый крутой редактор CSS, который мне приходилось вообще доводилось в жизни видеть. Dreamweaver отдыхает :). В XenForo настраивается все и настраивается вполне себе визуально. Забудьте о редактировании CSS напрямую, о листе с двумя тысячами переменных, который какой-томудак нехороший человек реализовал в VB. Здесь все очень грамотно сгруппировано так, что 99% секций помещаются на одном экране. Если вы не такой лох в плане дизайна, как я и имеете художественный вкус, наверное, вы можете уволить своего дизайнера, поскольку стиль вы сможете сделать и сами (через пару месяцев, как наиграетесь с редактором).
У вас есть база данных, скажем, от WordPress? Импортируйте пользователей из WP в базу XenForo с сохранением их паролей! Для того, чтобы потом все заработало, вам придется всего лишь расширить класс XenForo_Authentication_Abstract чтобы подсказать XenForo каким образом проверять пароль. Данные пользователей с вашими системами аутентификации связывает таблица xf_user_authenticate.
Уже достаточно давно на форумах позволяется указывать свои контакты в различных системах коммуникации типа ICQ. В XenForo существует легко расширяемая система контактных служб. Службы можно добавлять в панели управления. Класс поддержки службы выглядит примерно так:
Теперь уже никто не сможет ввести в поле ICQ своего профиля строчку «Продам носки шерстяные» :)
Каждая группа пользователей системы имеет права по умолчанию. Плюс права каждой группы можно дополнительно настроить в любом типе узла. Разумеется, привилегии наследуются.
Типов разрешений четыре. Inherit, Allow, Revoke, Deny. Пока мне не удалось понять, чем Revoke отличается от Deny. Причем, Revoke отсутствует в правах группы по умолчанию, что наталкивает на мысль, что этот тип связан с наследованием прав.
После переключения форума в режим отладки, вы сможете добавлять в систему новые типы привилегий (аддоны тоже могут их добавлять). В коде они проверяются примерно так:
Вообще код XenForo произвел на меня приятное впечатление. Он красивый, понятный, гармоничный, полон комментариев и ООП. Сначала, посмотрев на количество классов, я собирался испугаться и отложить статью до лучших времен, но теперь, подбираясь к концу, я могу сказать, что уже почти все ок, я немного въехал, как тут все устроено. Надеюсь, что и вы немножко тоже.
Кстати, я очень ждал выхода PHPBB3, хотел им заняться серьезно. Но его архитектура для меня выглядит гораздо менее четкой и логичной, чем архитектура XenForo. Честно признаться, я так и не въехал в PHPBB3. Будем ждать четверку на Symfony2…
Вот, пожалуй, и все. Вопросы по плагинам для XenForo можно задавать тут. А на официальном форуме уже есть несколько (18 на текущий момент), можно скачать и посмотреть. Сам я пока лицензию на движок не покупал, не было повода. Поэтому за предоставленный для изучения код благодарю моих друзей, уже купивших официальную версию.
Прошу прощения, если кому-то данная статья покажется неполной или некорректно построенной. Это мой первый обзор архитектуры чего-либо, поэтому я с радостью приму любую критику в комментариях. Часть критики, надо полагать, я сразу увижу на своей карме и рейтинге :) Если вам еще что-то интересно узнать, сообщите об этом в комментах, если сумею разобраться быстро — дополню статью.
В этой статье я постараюсь вкратце описать архитектуру нового форумного движка XenForo, нового конкурента VBulletin и IPB, насколько это у меня получится после пары часов знакомства с исходником. О XenForo, спроектированном бывшими авторами VBulletin3, Киром и Майком, я уже немного писал.

Размеры
Размер основной части кода XenForo 3,24 МБ (3 405 312 байт). Еще 8,31 МБ (8 724 429 байт) занимает Zend Framework, который поставляется вместе с кодом XenForo.
MVC
XenForo полностью основан на MVC архитектуре. Есть отдельные классы для моделей, видов и контроллеров. Корневой index.php имеет размер в 467 байт и заканчивается, как и положено в таких случаях
$fc = new XenForo_FrontController(new XenForo_Dependencies_Public());
$fc->run();Разумеется, в ходу автозагрузчик классов. Система именования классов как в ZF.
Сама MVC пока внутри использует классы Zend, но то, что XenForo_Controller не унаследован от соответствующих классов ZF, говорит о том, что эта часть будет переписана.
Все контроллеры унаследованы примерно одинаково: class XenForo_ControllerPublic_Forum extends XenForo_ControllerPublic_Abstract. После Symfony с ее actions такой подход несколько непривычен, но к нему быстро привыкаешь.
Система роутинга спроектирована расширяемой. Расширение происходит через привязку префиксов URL к классам-обработчикам. SEO из коробки, разумеется. Никаких плагинов не требуется.
Модель контента
Архитектура XenForo закладывалась надолго :) Во всяком случае, в первый раз в форумном движке я встретил более-менее внятную архитектуру контента, слегка напоминающую Drupal («Everything is a node», помните?). Пока в XenForo типов контента четыре: категория, раздел форума, страница и ссылка (обычный редирект). Каждый тоже называется Node. Причем, каждый экземпляр узла может быть предком/потомком экземпляра другого типа. Пока не знаю, как эта гремучая смесь, например, из страницы и дочернего ей раздела форума, будет отображаться, не пробовал :). Причем, некоторые типы контента можно слегка расширять прямо из коробки. Так, например, для страницы помимо, собственно, ее HTML содержимого можно указать PHP обработчик, который получит из БД дополнительные данные, изменит д��зайн страницы, вставит в нее информацию или вообще плюнет в пользователя ошибкой. PHP обработчики везде указываются не кодом на PHP, как этого можно было ожидать, а именами класса и метода. При активации хука класс будет загружен автолоадером (соответственно, должен быть правильно расположен в файловой системе).
Типы контента пока заданы жестко, самому добавить их не получится. Даже их названия в админке почему-то не локализованы.
Использование сторонних библиотек
XenForo использует Sabre и Zend Framework. Причем, наличие в коде мест, подобных
............
/*require_once('Zend/Loader/Autoloader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader(array($this, 'autoload'));*/
spl_autoload_register(array($this, 'autoload'));
скорее всего, означает, что от лишних зависимостей на протяжении разработки продолжат избавляться, заменяя их на что-то свое более легковесное и более специализированное.
Из ZF используется совсем немного классов. В их числе Zend_Registry (в качестве реестра для синглтон-подобных объектов вроде экземпляра XenForo_Db), Zend_Config, Zend_Cache (много чего кеширует, в частности используется в базовом классе моделей XenForo_Model), Zend_Service_ReCaptcha, Zend_Http_Client, Zend_Mail, Zend_Validate и некоторые другие.
Для работы с базой данных используется часть бандла Zend_DB (Zend_Db_Adapater_Abstract и Ко), завернутая в классе XenForo_DB, что опять говорит о том, что и эту часть в последствии перепишут.
Конструктор запросов не используется, они встроены прямо в код, как обычно (что, конечно, несколько затруднит поддержку нескольких баз данных. Но с другой стороны, запросы сконцентрированы внутри модели, так что...)
Архитектура аддонов
Для расширения форума предназначено несколько событий, на которые можно повесить обработчики. Обработчики указываются, как уже было сказано, через имя класса и метода, что позволяет использовать акселераторы вроде APC для кеширования аддонов. Список обработчиков вместе с базовой информацией о плагине помещается в *.xml файл. Писать его руками не обязательно. Достаточно активировать отладочный режим на форуме и в админке появятся дополнительные возможности. PHP файлы аддона, разумеется, надо будет сначала распаковать в соответствующую папку. Классы XenForo лежат в /library/XenForo, стало быть ваши будут лежать в /library/VasyaCorp. Меня это порадовало, поскольку довольно часто я занимался поиском остатков плагина в файловой системе при его удалении из VBulletin.
Поскольку практически каждый аддон должен иметь настройки, их можно создавать прямо в админке и экспортировать в *.xml плагина вместе с информацией о хуках. Располагаются они там же, где и настройки самого XenForo. Встраивать их можно в произвольные места раздела общих настроек XenForo. Устроено все примерно также, как это было в VBulletin. Очень удобно и практически нет необходимости писать код для их поддержки.
Меня немного удивило количество хуков. Я полагаю, все помнят оглушительное количество хуков в VBulletin, которое даже в голове нельзя было удержать? В XenForo хуков всего… 17! Такое количество объясняется их назначением. Вот их имена:
- container_admin_params
- container_public_params
- controller_pre_dispatch
- front_controller_post_view
- front_controller_pre_dispatch
- front_controller_pre_route
- front_controller_pre_view
- init_dependencies
- load_class_bb_code
- load_class_controller
- load_class_datawriter
- load_class_model
- load_class_route_prefix
- load_class_search_data
- load_class_view
- navigation_tabs
- visitor_setup
Небольшая инспекция кода показала, что семейство хуков load_class_* предназначено для динамического расширения системы классов XenForo. Вот ключевой кусочек кода:
public static function resolveDynamicClass($class, $type, $fakeBase = false)
{
if (!XenForo_Application::autoload($class))
{
if ($fakeBase)
{
$fakeNeeded = true;
}
else
{
return false;
}
}
else
{
$fakeNeeded = false;
}
if (!empty(self::$_classCache[$class]))
{
return self::$_classCache[$class];
}
$createClass = $class;
$extend = array();
XenForo_CodeEvent::fire('load_class_' . $type, array($class, &$extend));
if ($fakeNeeded)
{
if (!$extend)
{
return false;
}
eval('class ' . $class . ' extends ' . $fakeBase . ' {}');
}
if ($extend)
{
try
{
foreach ($extend AS $dynamicClass)
{
// XenForo Class Proxy, in case you're wondering
$proxyClass = 'XFCP_' . $dynamicClass;
eval('class ' . $proxyClass . ' extends ' . $createClass . ' {}');
XenForo_Application::autoload($dynamicClass);
$createClass = $dynamicClass;
}
}
catch (Exception $e)
{
self::$_classCache[$class] = $class;
throw $e;
}
}
self::$_classCache[$class] = $createClass;
return $createClass;
}
А несколько неожиданное для меня использование хука visitor_setup для изменения всего чего угодно на странице показано тут. Практически через любой хук вы можете залезть в сердце системы
В общем, малое число хуков, похоже, вполне себе компенсируется их мощью.
Система шаблонов
Как и во всех современных форумах в XenForo есть КУЧА шаблонов. Синтаксис довольно мощный (см. отрывки внизу), впрочем, этим уже никого не удивишь. Спецтеги пишутся как в PHPTAL («неймспейсированный» XML/HTML). Один шаблон может содержать несколько файлов. Например, шаблон forum_list содержит forum_list, node_list (он вставляется в forum_list), node_list.css, sidebar.css, sidebar_online_users. CSS в шаблоне подключается через xen:require, что позволяет кешировать все CSS файлы как угодно.
<xen:require css="node_list.css" />
<xen:if hascontent="true">
<fieldset>
<ol class="nodeList sectionMain" id="forums">
<xen:contentcheck>
<xen:foreach loop="$renderedNodes" value="$node">{xen:raw $node}</xen:foreach>
</xen:contentcheck>
</ol>
</fieldset>
</xen:if>
-------------------------------------
<xen:edithint template="node_link.css" />
-------------------------------------
<xen:contentcheck>
<xen:foreach loop="$onlineUsers.records" value="$user">
<xen:if is="{$user.is_moderator} OR {$user.is_admin}">
<li>
<xen:avatar user="$user" size="s" img="true" />
<a href="{xen:link members, $user}" class="username">{xen:helper richUserName, $user}</a>
<div class="muted">{xen:helper userTitle, $user}</div>
</li>
</xen:if>
</xen:foreach>
</xen:contentcheck>
Обратите внимание на использование хелперов в шаблонах. Хелпер, как и в Symfony, это просто метод класса. Например, вот код хелпера helperUserLink:
public static function helperUserLink(array $user)
{
return '<a href="'
. XenForo_Link::buildPublicLink('members', $user)
. '" class="username">'
. htmlspecialchars($user['username'])
. '</a>';
}
Поисковая машина
Поисковая машина в XenForo реализована в виде отдельного класса (в отличие от ненавидимой мною реализации в VB, в которой, по-моему, сами разработчики давно уже запутались, просто не сознаются в этом), унаследованного от XenForo_Search_SourceHandler_Abstract. В настоящий момент реализация только одна — MySqlFt.php (class XenForo_Search_SourceHandler_MySqlFt extends XenForo_Search_SourceHandler_Abstract), но в ближайшее время должен появится Sphinx. Мода такая нынче :) Форумы уже не те, что раньше. Растут, как на дрожжах…
В админке пока нет опции для активации другого поискового движка, но не надо забывать, что это все же Beta.
Система локализации
Система локализации практически полностью повторяет свой аналог из VBulletin с тем исключением, что фразовые группы отсутствуют вообще. Вот начало файла фраз английского языка:
<?xml version="1.0" encoding="utf-8"?>
<phrases>
<phrase title="1_more_message" global_cache="0" version_id="1000017" version_string="1.0.0 Alpha 7"><![CDATA[1 more message]]></phrase>
<phrase title="about" global_cache="0" version_id="1000015" version_string="1.0.0 Alpha 5"><![CDATA[About]]></phrase>
Каждый аддон может иметь собственные фразы. Языки можно экспортировать. Переводить аддоны можно прямо в админке.
Кстати, русская локализация XenForo уже почти готова.
Система стилей
Я не дизайнер и вообще у меня плохой вкус. Все, что касается дизайна и его разработки меня пугает. Но в XenForo мы видим древовидную систему стилей, аналогичную VB, в которой мы можем взять какой-то стиль за основу и изменить часть его настроек или шаблонов. Только Кир с Майком реализовали самый крутой редактор CSS, который мне приходилось вообще доводилось в жизни видеть. Dreamweaver отдыхает :). В XenForo настраивается все и настраивается вполне себе визуально. Забудьте о редактировании CSS напрямую, о листе с двумя тысячами переменных, который какой-то
Система аутентификации
У вас есть база данных, скажем, от WordPress? Импортируйте пользователей из WP в базу XenForo с сохранением их паролей! Для того, чтобы потом все заработало, вам придется всего лишь расширить класс XenForo_Authentication_Abstract чтобы подсказать XenForo каким образом проверять пароль. Данные пользователей с вашими системами аутентификации связывает таблица xf_user_authenticate.
Службы связи
Уже достаточно давно на форумах позволяется указывать свои контакты в различных системах коммуникации типа ICQ. В XenForo существует легко расширяемая система контактных служб. Службы можно добавлять в панели управления. Класс поддержки службы выглядит примерно так:
<?php
class XenForo_Model_IdentityService_Icq extends XenForo_Model_IdentityService_Abstract
{
protected function _getIdentityServiceId()
{
return 'icq';
}
static public function verifyAccountName(&$accountName, &$error)
{
if (!preg_match('/^\d+$/', $accountName))
{
$error = new XenForo_Phrase('please_enter_valid_icq_uin_using_numeric_characters_only');
return false;
}
return true;
}
}
Теперь уже никто не сможет ввести в поле ICQ своего профиля строчку «Продам носки шерстяные» :)
Система прав и привилегий
Каждая группа пользователей системы имеет права по умолчанию. Плюс права каждой группы можно дополнительно настроить в любом типе узла. Разумеется, привилегии наследуются.
Типов разрешений четыре. Inherit, Allow, Revoke, Deny. Пока мне не удалось понять, чем Revoke отличается от Deny. Причем, Revoke отсутствует в правах группы по умолчанию, что наталкивает на мысль, что этот тип связан с наследованием прав.
После переключения форума в режим отладки, вы сможете добавлять в систему новые типы привилегий (аддоны тоже могут их добавлять). В коде они проверяются примерно так:
$users[$userId]['canCleanSpam'] = (XenForo_Permission::hasPermission($visitor['permissions'], 'general', 'cleanSpam') && $this->getModelFromCache('XenForo_Model_User')->couldBeSpammer($users[$userId]));
Общие впечатления
Вообще код XenForo произвел на меня приятное впечатление. Он красивый, понятный, гармоничный, полон комментариев и ООП. Сначала, посмотрев на количество классов, я собирался испугаться и отложить статью до лучших времен, но теперь, подбираясь к концу, я могу сказать, что уже почти все ок, я немного въехал, как тут все устроено. Надеюсь, что и вы немножко тоже.
Кстати, я очень ждал выхода PHPBB3, хотел им заняться серьезно. Но его архитектура для меня выглядит гораздо менее четкой и логичной, чем архитектура XenForo. Честно признаться, я так и не въехал в PHPBB3. Будем ждать четверку на Symfony2…
Вот, пожалуй, и все. Вопросы по плагинам для XenForo можно задавать тут. А на официальном форуме уже есть несколько (18 на текущий момент), можно скачать и посмотреть. Сам я пока лицензию на движок не покупал, не было повода. Поэтому за предоставленный для изучения код благодарю моих друзей, уже купивших официальную версию.
Прошу прощения, если кому-то данная статья покажется неполной или некорректно построенной. Это мой первый обзор архитектуры чего-либо, поэтому я с радостью приму любую критику в комментариях. Часть критики, надо полагать, я сразу увижу на своей карме и рейтинге :) Если вам еще что-то интересно узнать, сообщите об этом в комментах, если сумею разобраться быстро — дополню статью.
