XOOPS 架構
本文檔提供了 XOOPS 系統架構的綜合概述,說明各種元件如何協同工作以建立靈活且可擴展的內容管理系統。
XOOPS 遵循模組化架構,將關注點分離成不同的層。該系統圍繞多個核心原則構建:
- 模組性:功能被組織成獨立、可安裝的模組
- 可擴展性:系統可以在不修改核心程式碼的情況下進行擴展
- 抽象化:資料庫和展示層從業務邏輯中抽象出來
- 安全性:內置的安全機制防止常見漏洞
graph TB subgraph Presentation["🎨 展示層"] Themes["主題"] Templates["Smarty 模板"] Blocks["區塊"] end
subgraph Application["⚙️ 應用層"] Modules["模組"] Preloads["預加載"] Controllers["控制器"] BlockHandlers["區塊處理程序"] end
subgraph Domain["📦 域層"] XoopsObject["XoopsObject"] Handlers["物件處理程序"] Criteria["Criteria 系統"] end
subgraph Infrastructure["🔧 基礎設施層"] Database["XoopsDatabase"] Cache["快取系統"] Session["會話管理器"] Security["安全層"] end
Presentation --> Application Application --> Domain Domain --> Infrastructure
style Presentation fill:#e8f5e9,stroke:#388e3c style Application fill:#e3f2fd,stroke:#1976d2 style Domain fill:#fff3e0,stroke:#f57c00 style Infrastructure fill:#fce4ec,stroke:#c2185b1. 展示層
Section titled “1. 展示層”展示層使用 Smarty 模板引擎處理使用者介面呈現。
關鍵元件:
- 主題:視覺樣式和佈局
- Smarty 模板:動態內容呈現
- 區塊:可重複使用的內容小工具
2. 應用層
Section titled “2. 應用層”應用層包含業務邏輯、控制器和模組功能。
關鍵元件:
- 模組:自包含的功能包
- 處理程序:資料操作類別
- 預加載:事件偵聽器和掛鉤
域層包含核心業務物件和規則。
關鍵元件:
- XoopsObject:所有域物件的基類
- 處理程序:域物件的 CRUD 操作
4. 基礎設施層
Section titled “4. 基礎設施層”基礎設施層提供核心服務,如資料庫存取和快取。
請求生命週期
Section titled “請求生命週期”理解請求生命週期對於有效的 XOOPS 開發至關重要。
XOOPS 2.5.x 頁面控制器流
Section titled “XOOPS 2.5.x 頁面控制器流”當前 XOOPS 2.5.x 使用頁面控制器模式,其中每個 PHP 檔案處理自己的請求。全域變數 ($xoopsDB、$xoopsUser、$xoopsTpl 等) 在啟動期間初始化,並在整個執行過程中可用。
sequenceDiagram participant Browser participant Entry as modules/mymod/index.php participant Main as mainfile.php participant Kernel as XOOPS Kernel participant DB as $xoopsDB participant User as $xoopsUser participant Handler as MyObjectHandler participant Tpl as $xoopsTpl (Smarty) participant Theme
Browser->>Entry: GET /modules/mymod/index.php
rect rgb(240, 248, 255) Note over Entry,User: 啟動階段 (mainfile.php) Entry->>Main: 包含 mainfile.php Main->>Kernel: 初始化核心 Kernel->>DB: 建立 XoopsDatabase (單體) Kernel->>User: 載入會話 → $xoopsUser Kernel->>Tpl: 初始化 Smarty → $xoopsTpl Main-->>Entry: 全域變數就緒 end
rect rgb(255, 250, 240) Note over Entry,Handler: 頁面控制器執行 Entry->>Handler: xoops_getModuleHandler('myobject') Handler->>DB: 透過 Criteria 查詢 DB-->>Handler: 結果集 Handler-->>Entry: XoopsObject[] end
rect rgb(240, 255, 240) Note over Entry,Theme: 呈現階段 Entry->>Tpl: $xoopsTpl->assign('items', $objects) Entry->>Theme: 包含 header.php Entry->>Tpl: $xoopsTpl->display('mymod_index.tpl') Entry->>Theme: 包含 footer.php Theme-->>Browser: 完整 HTML 頁面 end2.5.x 中的關鍵全域變數
Section titled “2.5.x 中的關鍵全域變數”| 全域變數 | 類型 | 初始化 | 用途 |
|---|---|---|---|
$xoopsDB | XoopsDatabase | 啟動 | 資料庫連線 (單體) |
$xoopsUser | XoopsUser|null | 會話載入 | 當前登錄使用者 |
$xoopsTpl | XoopsTpl | 模板初始化 | Smarty 模板引擎 |
$xoopsModule | XoopsModule | 模組載入 | 當前模組上下文 |
$xoopsConfig | array | 設定載入 | 系統設定 |
1. 啟動階段
Section titled “1. 啟動階段”// mainfile.php 是入點include_once XOOPS_ROOT_PATH . '/mainfile.php';
// 核心初始化$xoops = Xoops::getInstance();$xoops->boot();步驟:
- 載入設定 (
mainfile.php) - 初始化自動載入器
- 設定錯誤處理
- 建立資料庫連線
- 載入使用者會話
- 初始化 Smarty 模板引擎
2. 路由階段
Section titled “2. 路由階段”// 將請求路由到適當的模組$module = $GLOBALS['xoopsModule'];$controller = $module->getController();$controller->dispatch($request);步驟:
- 解析請求 URL
- 識別目標模組
- 載入模組設定
- 檢查權限
- 路由到適當的處理程序
3. 執行階段
Section titled “3. 執行階段”// 控制器執行$data = $handler->getObjects($criteria);$xoopsTpl->assign('items', $data);步驟:
- 執行控制器邏輯
- 與資料層互動
- 處理業務規則
- 準備檢視資料
4. 呈現階段
Section titled “4. 呈現階段”// 模板呈現include XOOPS_ROOT_PATH . '/header.php';$xoopsTpl->display('db:module_template.tpl');include XOOPS_ROOT_PATH . '/footer.php';步驟:
- 應用主題佈局
- 呈現模組模板
- 處理區塊
- 輸出回應
XoopsObject
Section titled “XoopsObject”所有 XOOPS 資料物件的基類。
<?phpclass MyModuleItem extends XoopsObject{ public function __construct() { $this->initVar('id', XOBJ_DTYPE_INT, null, false); $this->initVar('title', XOBJ_DTYPE_TXTBOX, '', true, 255); $this->initVar('content', XOBJ_DTYPE_TXTAREA, '', false); $this->initVar('created', XOBJ_DTYPE_INT, time(), false); }}關鍵方法:
initVar()- 定義物件屬性getVar()- 檢索屬性值setVar()- 設定屬性值assignVars()- 從陣列批量分配
XoopsPersistableObjectHandler
Section titled “XoopsPersistableObjectHandler”處理 XoopsObject 例項的 CRUD 操作。
<?phpclass MyModuleItemHandler extends XoopsPersistableObjectHandler{ public function __construct(\XoopsDatabase $db) { parent::__construct($db, 'mymodule_items', 'MyModuleItem', 'id', 'title'); }
public function getActiveItems($limit = 10) { $criteria = new CriteriaCompo(); $criteria->add(new Criteria('status', 1)); $criteria->setSort('created'); $criteria->setOrder('DESC'); $criteria->setLimit($limit);
return $this->getObjects($criteria); }}關鍵方法:
create()- 建立新物件例項get()- 按 ID 檢索物件insert()- 將物件儲存到資料庫delete()- 從資料庫移除物件getObjects()- 檢索多個物件getCount()- 計數匹配物件
每個 XOOPS 模組都遵循標準目錄結構:
modules/mymodule/├── class/ # PHP 類別│ ├── MyModuleItem.php│ └── MyModuleItemHandler.php├── include/ # 包含檔案│ ├── common.php│ └── functions.php├── templates/ # Smarty 模板│ ├── mymodule_index.tpl│ └── mymodule_item.tpl├── admin/ # 管理區域│ ├── index.php│ └── menu.php├── language/ # 翻譯│ └── english/│ ├── main.php│ └── modinfo.php├── sql/ # 資料庫架構│ └── mysql.sql├── xoops_version.php # 模組資訊├── index.php # 模組入點└── header.php # 模組頁首依賴注入容器
Section titled “依賴注入容器”現代 XOOPS 開發可以利用依賴注入來提高可測試性。
基本容器實現
Section titled “基本容器實現”<?phpclass XoopsDependencyContainer{ private array $services = [];
public function register(string $name, callable $factory): void { $this->services[$name] = $factory; }
public function resolve(string $name): mixed { if (!isset($this->services[$name])) { throw new \InvalidArgumentException("Service not found: $name"); }
$factory = $this->services[$name];
if (is_callable($factory)) { return $factory($this); }
return $factory; }
public function has(string $name): bool { return isset($this->services[$name]); }}PSR-11 相容容器
Section titled “PSR-11 相容容器”<?phpnamespace Xmf\Di;
use Psr\Container\ContainerInterface;
class BasicContainer implements ContainerInterface{ protected array $definitions = [];
public function set(string $id, mixed $value): void { $this->definitions[$id] = $value; }
public function get(string $id): mixed { if (!$this->has($id)) { throw new \InvalidArgumentException("Service not found: $id"); }
$entry = $this->definitions[$id];
if (is_callable($entry)) { return $entry($this); }
return $entry; }
public function has(string $id): bool { return isset($this->definitions[$id]); }}<?php// 服務登錄$container = new XoopsDependencyContainer();
$container->register('database', function () { return XoopsDatabaseFactory::getDatabaseConnection();});
$container->register('userHandler', function ($c) { return new XoopsUserHandler($c->resolve('database'));});
// 服務解析$userHandler = $container->resolve('userHandler');$user = $userHandler->get($userId);XOOPS 提供了多種擴展機制:
1. 預加載
Section titled “1. 預加載”預加載允許模組掛接到核心事件。
<?phpclass MymoduleCorePreload extends XoopsPreloadItem{ public static function eventCoreHeaderEnd($args) { // 在頁首處理結束時執行 }
public static function eventCoreFooterStart($args) { // 在頁尾處理開始時執行 }}2. 外掛程式
Section titled “2. 外掛程式”外掛程式擴展模組內的特定功能。
<?phpclass MymoduleNotifyPlugin{ public function onItemCreate($item) { // 建立項目時傳送通知 }}3. 篩選器
Section titled “3. 篩選器”篩選器修改通過系統的資料。
<?php// 內容篩選器示例$myts = MyTextSanitizer::getInstance();$content = $myts->displayTarea($rawContent, 1, 1, 1);-
為新程式碼使用命名空間:
namespace XoopsModules\MyModule;class Item extends \XoopsObject{// 實現} -
遵循 PSR-4 自動載入:
{"autoload": {"psr-4": {"XoopsModules\\MyModule\\": "class/"}}} -
分離關注點:
- 業務邏輯在
class/ - 展示在
templates/ - 控制器在模組根目錄
- 業務邏輯在
- 對昂貴操作使用快取
- 盡可能延遲載入資源
- 使用 criteria 批處理最小化資料庫查詢
- 透過避免複雜邏輯最佳化模板
- 使用
Xmf\Request驗證所有輸入 - 在模板中逸出輸出
- 對資料庫查詢使用準備好的語句
- 在敏感操作前檢查權限
#xoops #architecture #core #design #system-design