PHP 擴展透過 INI 設定暴露可配置參數。本文詳細解析 PHP_INI_BEGIN/END 定義語法、REGISTER_INI_ENTRIES 註冊流程、四種讀取宏、三層存取層級 (PHP_INI_SYSTEM/PERDIR/USER/ALL) 與修改回調機制。
INI 設定定義語法
#include "php_ini.h"
PHP_INI_BEGIN()
// 標準項目:名稱、預設值、存取層級、修改回調
PHP_INI_ENTRY("sample4.greeting", "Hello World", PHP_INI_ALL, NULL)
// 整數項目
PHP_INI_ENTRY("sample4.max_items", "100", PHP_INI_ALL, NULL)
// 布林項目
PHP_INI_ENTRY("sample4.debug_mode", "0", PHP_INI_ALL, NULL)
// 帶修改回調
PHP_INI_ENTRY("sample4.api_key", "", PHP_INI_SYSTEM, OnUpdateAPIKey)
PHP_INI_END()
MINIT/MSHUTDOWN 註冊與銷毀
PHP_MINIT_FUNCTION(sample4) {
REGISTER_INI_ENTRIES(); // 向 Zend 註冊所有 PHP_INI_ENTRY
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(sample4) {
UNREGISTER_INI_ENTRIES(); // 移除註冊
return SUCCESS;
}
四種讀取宏 (在函式中使用)
| 宏 | 回傳型別 | 用途 | 範例 |
INI_STR(name) | const char * | 字串值 (引擎擁有,勿修改) | const char *g = INI_STR("sample4.greeting"); |
INI_INT(name) | long | 整數值 | long max = INI_INT("sample4.max_items"); |
INI_FLT(name) | double | 浮點數值 | double ratio = INI_FLT("sample4.ratio"); |
INI_BOOL(name) | zend_bool | 布林值 | zend_bool debug = INI_BOOL("sample4.debug_mode"); |
原始值讀取宏 (忽略運行時修改)
| 宏 | 說明 |
INI_ORIG_STR(name) | 原始字串值 (php.ini 載入時的值) |
INI_ORIG_INT(name) | 原始整數值 |
INI_ORIG_FLT(name) | 原始浮點數值 |
INI_ORIG_BOOL(name) | 原始布林值 |
實戰範例:問候語函式
PHP_FUNCTION(sample4_hello_world) {
const char *greeting = INI_STR("sample4.greeting");
php_printf("%s\n", greeting);
}
// 使用整數設定
PHP_FUNCTION(sample4_get_max) {
long max = INI_INT("sample4.max_items");
RETURN_LONG(max);
}
存取層級詳細解析
| 層級常數 | 可修改位置 | 典型用途 |
PHP_INI_USER | ini_set()、.user.ini | 使用者可調整 (如顯示設定) |
PHP_INI_PERDIR | .htaccess、httpd.conf (目錄級) | 目錄級配置 (如上傳限制) |
PHP_INI_SYSTEM | php.ini、httpd.conf (全域) | 系統級敏感設定 (如 API 金鑰) |
PHP_INI_ALL | 以上皆可 | 完全開放調整 |
層級選擇原則
- 預設使用
PHP_INI_ALL 以利開發測試。
- 涉及安全 (密鑰、路徑、資源限制) →
PHP_INI_SYSTEM。
- 目錄級差異化需求 →
PHP_INI_PERDIR。
- 僅運行時動態調整 →
PHP_INI_USER。
修改回調函式 (OnModify)
// 回調原型
ZEND_INI_MH(OnUpdateAPIKey) {
// new_value: 新值字串
// new_value_length: 長度
// mh_arg1/2/3: PHP_INI_ENTRY 額外參數 (鮮少使用)
// stage: 修改階段 (PHP_INI_STAGE_STARTUP/RUNTIME/HTACCESS)
if (stage == PHP_INI_STAGE_RUNTIME) {
// 運行時修改,可做額外驗證
if (strlen(new_value) < 16) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "API key too short");
return FAILURE; // 拒絕修改
}
}
// 更新全域變數或執行副作用
OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
return SUCCESS;
}
// 註冊時指定回調
PHP_INI_ENTRY("sample4.api_key", "", PHP_INI_SYSTEM, OnUpdateAPIKey)
命名慣例
建議格式:extname.setting_name (如 sample4.greeting),避免跨擴展衝突。私有擴展可簡化,公開發布擴展**必須**遵循。