XenForo:プログラマ向けのフォーラムアーキテクチャの概要

こんにちは

この記事では、VBulletinとIPBの新しいライバルである新しいフォーラムエンジンXenForoのアーキテクチャ、ソースを数時間知った後にどれだけ成功するかを簡単に説明します。 VBulletin3の元作者であるCyrusとMikeによって設計されたXenForoについては、すでに少し書いています。




寸法


XenForoコードの主要部分のサイズは3.24 MB(3 405 312バイト)です。 別の8.31 MB(8 724 429バイト)は、XenForoコードに付属するZend Frameworkによって占有されています。

MVC


XenForoは完全にMVCアーキテクチャに基づいています。 モデル、ビュー、コントローラー用に個別のクラスがあります。 ルートindex.phpのサイズは467バイトで、そのような場合に必要なように終了します
$fc = new XenForo_FrontController(new XenForo_Dependencies_Public()); $fc->run(); 

もちろん、クラスオートローダーは使用中です。 ZFのようなクラス命名システム。

MVC自体はまだZendクラスを内部で使用していますが、XenForo_Controllerが対応するZFクラスから継承されていないという事実は、この部分が書き換えられることを示唆しています。

すべてのコントローラーはほぼ同じ方法で継承されます。クラスXenForo_ControllerPublic_ForumはXenForo_ControllerPublic_Abstractを拡張します。 Symfonyのアクションの後、このアプローチはやや珍しいですが、すぐに慣れます。

ルーティングシステムは拡張可能に設計されています。 拡張は、URLプレフィックスをハンドラクラスにバインドすることで発生します。 もちろん、すぐに使えるSEOです。 プラグインは必要ありません。

コンテンツモデル


XenForoアーキテクチャは長い間敷かれていました:)とにかく、フォーラムエンジンで初めて、多少なりともDrupalを連想させるわかりやすいコンテンツアーキテクチャに出会いました(「すべてがノード」、覚えていますか?)。 これまでのところ、XenForoには、カテゴリ、フォーラムセクション、ページ、およびリンク(通常のリダイレクト)の4種類のコンテンツがあります。 それぞれはノードとも呼ばれます。 さらに、ノードの各インスタンスは、別のタイプのインスタンスの祖先/子孫になることができます。 この爆発的な混合物が、たとえばページとそのフォーラムセクションからどのように表示されるかはまだわかりませんが、試していません:)。 さらに、一部の種類のコンテンツは、箱から出してすぐに拡張できます。 したがって、たとえば、ページの場合、実際にはそのHTMLコンテンツに加えて、データベースから追​​加データを受信するPHPハンドラーを指定したり、ページのデザインを変更したり、情報を挿入したり、ユーザーにエラーを投げたりすることさえできます。 どこでもPHPハンドラーは、予想されるようにPHPコードではなく、クラス名とメソッド名で示されます。 フックがアクティブになると、クラスはオートラダーによってロードされます(したがって、ファイルシステムに正しく配置されている必要があります)。

コンテンツタイプは依然としてハードコードされているため、自分で追加することはできません。 なんらかの理由で、管理領域の名前もローカライズされていません。

サードパーティのライブラリを使用する


XenForoはSaberと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、いくつかのZendalid。

データベースを操作するには、XendForo_DBクラスでラップされたZend_DBバンドルの一部(Zend_Db_Adapater_AbstractおよびCo.)を使用します。これは、この部分も後で書き換えられることを示しています。

クエリデザイナは使用されず、通常どおりコードに直接組み込まれます(もちろん、複数のデータベースをサポートするのは多少困難になります。しかし一方で、クエリはモデル内に集中しているため...)

アドオンアーキテクチャ


フォーラムを拡張するために、ハンドラーをハングアップできるイベントがいくつか用意されています。 既に述べたように、ハンドラーはクラスとメソッドの名前で示されます。これにより、APCなどのアクセラレーターを使用してアドオンをキャッシュできます。 ハンドラーのリストとプラグインに関する基本情報は、* .xmlファイルに配置されます。 手書きはオプションです。 フォーラムでデバッグモードをアクティブ化するだけで十分で、追加機能が管理パネルに表示されます。 もちろん、PHPアドオンファイルは、最初に適切なフォルダーに展開する必要があります。 XenForoクラスは/ library / XenForoにあるため、/ library / VasyaCorpにあります。 VBulletinから削除されたときに、ファイルシステムでプラグインの残りを頻繁に探していたため、これに満足していました。

ほとんどすべてのアドオンに設定が必要なので、管理パネルで直接作成し、フックに関する情報とともに* .xmlプラグインにエクスポートできます。 これらは、XenForo自体の設定と同じ場所にあります。 XenForoの一般設定セクションの任意の場所に埋め込むことができます。 すべてがVBulletinの場合とほぼ同じように配置されます。 これは非常に便利であり、それらをサポートするコードを書く必要はほとんどありません。

フックの数に少し驚いた。 私は誰もが頭に留めることさえできなかったVBulletinのフックの耳障りな量を覚えていると思いますか? XenForoには17個のフックしかない! そのような量は、その目的によって説明されます。 名前は次のとおりです。



小規模なコード検査により、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)のように記述されています。 1つのテンプレートに複数のファイルを含めることができます。 たとえば、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の検索エンジンは、XenForo_Search_SourceHandler_Abstractから継承された別のクラスとして実装されます(VBで私が嫌いな実装とは異なり、開発者自身は長い間混乱してきたため、単純に認めていません)。 現在、MySqlFt.php(クラスXenForo_Search_SourceHandler_MySqlFtはXenForo_Search_SourceHandler_Abstractを拡張します)は1つしか実装されていませんが、近い将来Sphinxが登場するはずです。 今日のファッションはそうです:)フォーラムは以前と同じではありません。 飛躍的に成長し......

管理パネルには別の検索エンジンを有効にするオプションはありませんが、これがまだベータ版であることを忘れないでください。

ローカリゼーションシステム


ローカリゼーションシステムは、フレーズグループがまったくないことを除いて、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に似たツリーのようなスタイルシステムがあります。このシステムでは、いくつかのスタイルをベースにして、その設定またはテンプレートの一部を変更できます。 CyrusとMikeだけが、私が今まで見た中で最もクールなCSSエディターを実装しました。 Dreamweaverは休んでいます:)。 XenForoでは、すべてが非常に視覚的に構成および構成されます。 2,000個の変数を持つシートについては、CSSを直接​​編集することを忘れてください。 ここでは、セクションの99%が1つの画面に収まるように、すべてが非常に適切にグループ化されています。 私が芸術的な趣味を持っているので、デザインの面であなたが吸盤ではない場合、おそらくあなたは自分でスタイルを作ることができるので、おそらくあなたのデザイナーを解任することができます(数ヶ月で、エディターで十分に遊んでいる間)。

認証システム


たとえば、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フィールドに「Selling wool socks」という行を入力することはできません。

権利と特権のシステム


システムの各ユーザーグループには、デフォルトで権限があります。 さらに、各グループの権限は、任意のタイプのノードで追加で構成できます。 もちろん、特権は継承されます。

許可には4つのタイプがあります。 継承、許可、取り消し、拒否。 これまで、RevokeとDenyの違いを理解できませんでした。 さらに、デフォルトでは、Revokeはグループの権利に含まれていません。これは、このタイプが権利の継承に関連付けられていることを示しています。

フォーラムをデバッグモードに切り替えた後、システムに新しい種類の特権を追加できます(アドオンで追加することもできます)。 コードでは、次のようにチェックされます。
 $users[$userId]['canCleanSpam'] = (XenForo_Permission::hasPermission($visitor['permissions'], 'general', 'cleanSpam') && $this->getModelFromCache('XenForo_Model_User')->couldBeSpammer($users[$userId])); 


一般的な印象


一般的に、XenForoコードは私に良い印象を与えました。 彼は美しく、理解しやすく、調和があり、コメントとOOPに満ちています。 最初は、クラスの数を見て、怖がって記事を延期する予定でしたが、今では終わりに近づいて、ほとんどすべてが大丈夫だと言えます。 皆さんも少しでもいいと思います。

ところで、私は本当にPHPBB3を楽しみにしていたので、真剣にやりたかったのです。 しかし、私にとっては、そのアーキテクチャはXenForoのアーキテクチャほど明確で論理的ではありません。 正直なところ、私はPHPBB3に入ったことはありません。 Symfony2の4つを待ちます...

おそらくそれだけです。 XenForoのプラグインに関する質問は、 こちらで確認できます公式フォーラムには既にいくつか(現在18)あり、ダウンロードして確認できます。 私自身はまだエンジンのライセンスを購入していません。理由はありません。 したがって、研究用に提供されたコードについては、すでに公式バージョンを購入した友人に感謝します。

この記事が不完全であるか、誰かに誤って作成されているように思われる場合は、謝罪します。 これはあらゆるアーキテクチャの私の最初のレビューなので、コメントでの批判を喜んで受け入れます。 批判の一部は、すぐに私のカルマと評価を見ると思います:)何かを学ぶことにまだ興味があるなら、コメントで知らせてください、すぐに理解できるなら、私は記事を完成させます。

Source: https://habr.com/ru/post/J105751/


All Articles