市面上成熟的 PHP 框架不少,但對初學者來說往往過於沉重、黑盒感強。筆者決定從零寫一個 教學導向的核心類庫——Machine_m,繼承 Smarty 模板引擎,整合資料庫操作、錯誤處理、靜態頁生成、二維陣列排序、分頁、表單驗證、防 XSS、中文截取、檔案上傳、文本佔位符替換等高頻功能。代碼開源、結構清晰、註釋詳盡,適合新手閱讀學習,也歡迎大佬指正優化。
| 模組 | 核心方法 | 特色亮點 |
|---|---|---|
| 資料庫 | send_query()、select_query() | 支援 MySQL/Access 雙引擎,配置文件驅動 |
| 錯誤處理 | sys_err()、user_err() | 系統/用戶錯誤分級,支援日誌記錄、模板化錯誤頁、跳轉控制 |
| 靜態生成 | create_html()、goto_html() | 一鍵生成靜態頁,支援過期時間、分頁靜態化 |
| 二維陣列排序 | m_sort() | 多欄位混合排序:m_sort($arr, 'name', SORT_ASC, 'age', SORT_DESC) |
| 動態載入 | load_func() | 按需載入外部函數檔,節省記憶體 |
| 分頁 | m_page() | 返回結構化分頁資訊:當前頁、總頁數、跳轉鏈接陣列、SQL LIMIT 參數 |
| 表單驗證 | 內建驗證邏輯 | 直接傳入 $_POST 即可,業務規則可自訂 |
| 防跨站攻擊 | 輸入過濾函數 | 整合在核心方法中,開箱即用 |
| 中文截取 | m_substr() | 支援多字節編碼,避免亂碼 |
| 檔案上傳 | m_up_file() | 支援按副檔名自動分目錄、多類型限制、詳細錯誤回報 |
| 文本操作 | m_txt_replace/add/delete/get() | 佔位符模式:<!--tag-->content<!--/tag-->,靜態頁局部更新利器 |
Machine_mclass Machine_m extends Smarty {
// 私有屬性
private $conn; // 資料庫連線資源
private $the_dir; // 專案根目錄
private $config; // 解析後配置物件
private $func_list; // 外部函數映射表
// 公開屬性
public $err_page = 'lib/error/err_page.htm'; // 錯誤模板
public $html_cache = 'html'; // 靜態輸出目錄
public $html_cache_lifetime = 86400; // 靜態過期秒數
public function __construct($test = false) {
// 保留 Smarty 初始化
$this->assign('SCRIPT_NAME', $_SERVER['SCRIPT_NAME'] ?? $GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
// Machine_m 專屬初始化
$this->left_delimiter = '<%';
$this->right_delimiter = '%>';
$this->the_dir = THIS_DIR;
$this->config_url = "{$this->the_dir}lib/config/config.php";
$this->config = $this->parse_ini();
$this->func_list_url = "{$this->the_dir}lib/config/func_list.php";
$this->func_list = $this->parse_func();
$this->state($test); // 環境模式:測試/正式
$this->load_func(array('m_addslashes', 'm_stripslashes')); // 核心函數預載
$this->connect(); // 資料庫連線
}
// 環境模式切換
private function state($test) {
if ($test) {
$this->load_func(array('m_print_r', 'm_var_dump'));
$this->compile_check = true;
error_reporting(E_ALL);
} else {
$this->compile_check = false;
error_reporting(0);
}
}
// 配置文件解析(INI 格式)
private function parse_ini() {
if (!file_exists($this->config_url)) $this->sys_err("config配置文件丟失", 'die');
$config = parse_ini_file($this->config_url);
// 驗證必要鍵:host_name, user_name, db_name, password
$config = $this->decode_config($config); // 可覆寫實現解密
return (object)$config; // 轉為物件便於 $config->host_name 存取
}
// 動態載入外部函數
public function load_func($func) {
foreach ((array)$func as $name) {
$this->include_file($this->func_list[$name]);
}
}
// 安全包含檔案
public function include_file($file_url) {
$file_url = $this->the_dir . $file_url;
if (!@include_once($file_url)) $this->sys_err("文件{$file_url}加載失敗", 'die');
}
// 資料庫連線工廠
private function connect() {
switch (strtoupper($this->config->database)) {
case 'MYSQL': $this->connect_mysql(); break;
case 'ACCESS': $this->connect_access(); break;
default: $this->sys_err('不支援的資料庫類型', 'die');
}
}
// MySQL 連線(含重連邏輯)
private function connect_mysql() {
if ($this->conn) { @mysql_close($this->conn); $this->conn = null; }
$this->conn = @mysql_connect($this->config->host_name, $this->config->user_name, $this->config->password);
if (!$this->conn) $this->sys_err("MySQL連線失敗: " . mysql_error(), 'die');
if (!@mysql_select_db($this->config->db_name, $this->conn))
$this->sys_err("選擇資料庫失敗: " . mysql_error(), 'die');
}
// Access 連線(ODBC)
private function connect_access() {
if ($this->conn) { @odbc_close($this->conn); $this->conn = null; }
$dsn = 'Driver=Microsoft Access Driver (*.mdb);dbq=' . realpath($this->the_dir . $this->config->db_name);
$this->conn = @odbc_connect($dsn, $this->config->user_name, $this->config->password);
if (!$this->conn) $this->sys_err("Access連線失敗: " . odbc_errormsg($this->conn), 'die');
}
}
config.php 中加密存放,decode_config() 留作擴展點供子類實現解密func_list.php 維護函數名→檔案路徑映射,實現「按需載入」,避免單檔過大// 系統錯誤:記錄日誌、可選 die、可自訂前台提示
$this->sys_err('配置錯誤', 'die', '自訂提示訊息');
// 用戶錯誤:前台提示、跳轉、可選記錄日誌
$m->user_err('註冊已關閉', 'die', $_SERVER['HTTP_REFERER'], '記錄內容');
錯誤頁面預設使用 Smarty 模板 lib/error/err_page.htm,可透過 $m->err_page 自訂。
$m->create_html('template.htm', 'html/', 'list_1.htm'); // 生成靜態檔
$m->goto_html(); // 跳轉至靜態頁,自動判斷過期時間
進階用法:結合 m_txt_replace() 實現「偽靜態」局部更新——評論直接寫入靜態檔佔位符,無需查資料庫,極大提升高併發下的讀取效能(參考 6to23 架構)。
$str = "你好<!--content-->phpchina<!--/content-->";
$new = m_txt_replace('content', 'machine_馬', $str);
// 結果:你好<!--content-->machine_馬<!--/content-->
同系列:m_txt_add(插入)、m_txt_delete(刪除)、m_txt_get(提取)。
unset($GLOBALS, $HTTP_*_VARS) 防止變量注入m_addslashes/m_stripslashes 統一處理魔術引號config.php、func_list.php、模板目錄結構Machine_m 構造函數,掌握初始化順序m_json_encode),體驗動態載入機制create_html + m_txt_replace 實現一個「高併發留言板」框架不是拿來崇拜的,是拿來拆解、理解、最終超越的。這個類庫不完美,但它把「一個 PHP 請求的生命週期」展示得淋漓盡致——這才是新手最寶貴的財富。