INI設(shè)定
和上一章你看到的超級(jí)全域變數(shù)以及持久化常數(shù)一樣, php.iniini值必須在執(zhí)行的MINIT變數(shù)和其他特性不同的是, INI選項(xiàng)的定義僅由簡(jiǎn)單的啟動(dòng)/終止線組成.
PHP_MINIT_FUNCTION(sample4) { REGISTER_INI_ENTRIES(); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(sample4) { UNREGISTER_INI_ENTRIES(); return SUCCESS; }
定義並訪問(wèn)INI設(shè)置
INI指令本身是在源碼文件中MINIT函數(shù)上面下面的巨集完全獨(dú)立的定義的, 在這兩個(gè)巨集之間可以定義一個(gè)或多個(gè)INI指令:
PHP_INI_BEIGN() PHP_INI_END()
這兩個(gè)宏函數(shù)和ZEND_BEGIN_MODULE_GLGLGLMOm/ENDEND不過(guò)這裡不是typdef一個(gè)結(jié)構(gòu)體, 而是對(duì)靜態(tài)資料實(shí)例定義的框架組織:
static zend_ini_entry ini_entries[] = { {0,0,NULL,0,NULL,NULL,NULL,NULL,NULL,0,NULL,0,0,NULL} };
如你所見(jiàn), 它定義了一個(gè)zend_ini_entry值的向量, 以空的向量記錄. 這和你在前面看到的靜態(tài)向量function_entry的定義一致.
簡(jiǎn)單的INI設(shè)定
現(xiàn)在, 你已經(jīng)有一個(gè)INI結(jié)構(gòu)體用於定義INI指令, 以及引擎註冊(cè)指令I(lǐng)NI設(shè)定的機(jī)制, 因此我們可以真正的去為你的擴(kuò)展定義一些INI指令了. 假設(shè)你的擴(kuò)展暴露了一個(gè)打招呼的函數(shù), 就像第5章"你的第一個(gè)擴(kuò)展"中一樣, 不過(guò),你想要讓打招呼的話可以自訂:
PHP_FUNCTION(sample4_hello_world) { php_printf("Hello World!\n"); }
最簡(jiǎn)單最直接的方式就是定義一個(gè)INI指令, 並給它一個(gè)預(yù)設(shè)值"Hello world!":
rrrereee你
可能已經(jīng)猜到了, 這個(gè)宏的前兩個(gè)參數(shù)表示INI指令的名字和它的默認(rèn)值. 第三個(gè)參數(shù)用來(lái)確定引擎是否允許這個(gè)INI指令被修改(這將涉及到本章後面要介紹的訪問(wèn)級(jí)別問(wèn)題). 最後一個(gè)參數(shù)是一個(gè)回調(diào)函數(shù), 它將在每次INI指令的值發(fā)生變化時(shí)被調(diào)用. 你將在修改事件一節(jié)看到這個(gè)參數(shù)的細(xì)節(jié).
譯註: 如果你和譯者一樣遇到結(jié)果和原著結(jié)果預(yù)期不一致時(shí), 請(qǐng)?jiān)跍y(cè)試時(shí), 在你的MINIT()函數(shù)中增加一句"REGISTER_INI_ENTRIES();"調(diào)用, 並確保該調(diào)用在你的MINIT中分配全局空間之後執(zhí)行.
現(xiàn)在你的INI設(shè)定已經(jīng)定義, 只需要在你的打招呼函數(shù)中使用就可以了.
#include "php_ini.h" PHP_INI_BEGIN() PHP_INI_ENTRY("sample4.greeting", "Hello World", PHP_INI_ALL, NULL) PHP_INI_END()一定要注意, char *的值是引擎所有的, 一定不要修改. 正因?yàn)檫@樣, 所以將你本地用來(lái)臨時(shí)儲(chǔ)存INI設(shè)定值的變數(shù)定義為const修飾. 當(dāng)然, 並不是所有的INI值都是字串; 還有其他的宏用來(lái)取得整數(shù), 浮點(diǎn)型以及布爾型的值:
PHP_FUNCTION(sample4_hello_world) { const char *greeting = INI_STR("sample4.greeting"); php_printf("%s\n", greeting); }
通常你想要知道的是INI設(shè)定的當(dāng)前值; 不過(guò), 作為補(bǔ)充, 存在幾個(gè)宏可以用來(lái)讀取未經(jīng)修改的INI設(shè)定值:
long lval = INI_INT("sample4.intval"); double dval = INI_FLT("sample4.fltval"); zend_bool bval = INI_BOOL("sample4.boolval");
這個(gè)例子中, INI指令的名字"sample4.greeting"增加了擴(kuò)展名作為前綴, 這樣來(lái)保證不會(huì)和其他擴(kuò)展暴露的INI指令名字衝突. 對(duì)於私有的擴(kuò)展來(lái)說(shuō), 這個(gè)前綴不是必須的, 但是對(duì)於商業(yè)化或開(kāi)源發(fā)布的公開(kāi)擴(kuò)展還是鼓勵(lì)這樣做的.
訪問(wèn)級(jí)別
對(duì)於INI默認(rèn)指令值值不變; 然而, 對(duì)於某些特殊的環(huán)境或腳本內(nèi)特定的動(dòng)作, 這些值可能需要被修改. 如下表所示, INI指令的值可能在下面3個(gè)點(diǎn)被修改:
訪問(wèn)等級(jí) | 意義 | |||||||||
php.ini | ,或 apache的httpd.conf設(shè)定檔 | 位於Apache的httpd.conf設(shè)定檔中 | 去修改||||||||
設(shè)定了. INI | 某些設(shè)置如果可以在任何地方被修改就沒(méi)有多大意義了, 比如safe_mode, 如果可以在任何地方去修改, 那么惡意腳本的作者就可以很簡(jiǎn)單的去禁用safe_mode, 接著去讀或修改本不允許操作的文件. 類(lèi)似的, 某些非安全相關(guān)的指令比如register_globals或magic_quotes_gpc, 在腳本中不能被修改, 因?yàn)? 在腳本執(zhí)行時(shí), 它所影響的事情已經(jīng)發(fā)生過(guò)了. 這些指令的訪問(wèn)控制是通過(guò)PHP_INI_ENTRY()的第三個(gè)參數(shù)完成的. 在你前面例子中, 使用了PHP_INI_ALL, 它的定義是一個(gè)位域操作: PHP_INI_SYSTEM | PHP_INI_PERDIR | PHP_INI_USER. 對(duì)于register_globals和magic_quotes_gpc這樣的指令, 定義的訪問(wèn)級(jí)別為PHP_INI_SYSTEM | PHP_INI_PERDIR. 排除了PHP_INI_USER將導(dǎo)致以這個(gè)名字調(diào)用ini_set()時(shí)最終會(huì)失敗. 現(xiàn)在, 你可能已經(jīng)猜到, safe_mode和open_basedir這樣的指令應(yīng)該僅被定義為PHP_INI_SYSTEM. 這樣的設(shè)置就確保了只有系統(tǒng)管理員可以修改這些值, 因?yàn)橹挥兴鼈兛梢栽L問(wèn)修改php.ini或httpd.conf文件中的配置. 修改事件 當(dāng)INI指令被修改時(shí), 無(wú)論是通過(guò)ini_set()函數(shù)還是某個(gè)perdir指令的處理, 引擎都會(huì)為其測(cè)試OnModify回調(diào). 修改處理器可以使用ZEND_INI_MH()宏定義, 并通過(guò)在OnModify參數(shù)上傳遞函數(shù)名附加到INI指令上: ZEND_INI_MH(php_sample4_modify_greeting) { if (new_value_length == 0) { return FAILURE; } return SUCCESS; } PHP_INI_BEGIN() PHP_INI_ENTRY("sample4.greeting", "Hello World", PHP_INI_ALL, php_sample4_modify_greeting) PHP_INI_END() 通過(guò)在new_value_length為0時(shí)返回FAILURE, 這個(gè)修改處理器禁止將greeting設(shè)置為空字符串. ZEND_INI_MH()宏產(chǎn)生的整個(gè)原型如下: int php_sample4_modify_greeting(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC); 各個(gè)參數(shù)的含義見(jiàn)下表:
|