INI設(shè)定了. INI |
某些設(shè)置如果可以在任何地方被修改就沒有多大意義了, 比如safe_mode, 如果可以在任何地方去修改, 那么惡意腳本的作者就可以很簡單的去禁用safe_mode, 接著去讀或修改本不允許操作的文件. 類似的, 某些非安全相關(guān)的指令比如register_globals或magic_quotes_gpc, 在腳本中不能被修改, 因為, 在腳本執(zhí)行時, 它所影響的事情已經(jīng)發(fā)生過了. 這些指令的訪問控制是通過PHP_INI_ENTRY()的第三個參數(shù)完成的. 在你前面例子中, 使用了PHP_INI_ALL, 它的定義是一個位域操作: PHP_INI_SYSTEM | PHP_INI_PERDIR | PHP_INI_USER. 對于register_globals和magic_quotes_gpc這樣的指令, 定義的訪問級別為PHP_INI_SYSTEM | PHP_INI_PERDIR. 排除了PHP_INI_USER將導致以這個名字調(diào)用ini_set()時最終會失敗. 現(xiàn)在, 你可能已經(jīng)猜到, safe_mode和open_basedir這樣的指令應(yīng)該僅被定義為PHP_INI_SYSTEM. 這樣的設(shè)置就確保了只有系統(tǒng)管理員可以修改這些值, 因為只有它們可以訪問修改php.ini或httpd.conf文件中的配置. 修改事件 當INI指令被修改時, 無論是通過ini_set()函數(shù)還是某個perdir指令的處理, 引擎都會為其測試OnModify回調(diào). 修改處理器可以使用ZEND_INI_MH()宏定義, 并通過在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() 通過在new_value_length為0時返回FAILURE, 這個修改處理器禁止將greeting設(shè)置為空字符串. ZEND_INI_MH()宏產(chǎn)生的整個原型如下:
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); 各個參數(shù)的含義見下表:
參數(shù)名 | 含義 | entry | 指向引擎真實儲存的INI指令項.這個結(jié)構(gòu)體提供了當前值以及其他一些下面程式碼(zend_ini_entry結(jié)構(gòu)體結(jié)構(gòu))列出的資訊 .如果處理器回傳 SUCCESS, | 這個值將被設(shè)定到 entry->value,同時如果entry->orig_value | 中,並設(shè)定中,並設(shè)定entry->modified標記.這個字串的長度透過 mh_arg1, 2 , 3 | 這3個指針對應(yīng)INI指令定義時給出的資料指標(zend_entry指令定義時給出的資料指標(zend_entry 實際上,這幾個值是引擎內(nèi)部處理使用的,你不需要關(guān)心它們. STAGE_系列的 | 5 個值之一:
STARTUP, SHUTDOWN, ACTIVATE, DEACTIVATE, RUNTIME. 這些常數(shù)對應(yīng)於 | MINIT, MSHUTDOWN, RINIT, RSHUTDOWN,以及活性腳本執(zhí)行??????
核心結(jié)構(gòu)體: zend_ini_entry struct _zend_ini_entry {
int module_number;
int modifiable;
char *name;
uint name_length;
ZEND_INI_MH((*on_modify));
void *mh_arg1;
void *mh_arg2;
void *mh_arg3;
char *value;
uint value_length;
char *orig_value;
uint orig_value_length;
int modified;
void ZEND_INI_DISP(*displayer);
}; 展示INI設(shè)置 在上一章, 你看到了MINFO函數(shù)以及相關(guān)的指令用于展示擴展的信息. 由于擴展暴露INI指令是很常見的, 因此引擎提供了一個公共的宏可以放置到PHP_MINFO_FUNCTION()中用于展示INI指令信息.
PHP_MINFO_FUNCTION(sample4)
{
DISPLAY_INI_ENTRIES();
} 這個宏將迭代PHP_INI_BEGIN()和PHP_INI_END()宏之間定義的INI指令集和, 在一個3列的表格中展示它們的INI指令名, 原始值(全局的), 以及當前值(經(jīng)過PERDIR指令或ini_set()調(diào)用修改后) 默認情況下, 所有的指令都直接以其字符串形式輸出. 對于某些指令, 比如布爾值以及用于語法高亮的顏色值, 則在展示處理時應(yīng)用了其他格式. 這些格式是通過每個INI設(shè)置的顯示處理器處理的, 它和你看到的OnModify一樣是一個動態(tài)的回調(diào)函數(shù)指針. 顯示處理器可以使用PHP_INI_ENTRY()宏的擴展版指定, 它接受一個額外的參數(shù). 如果設(shè)置為NULL, 則使用展示字符串值的處理器作為默認處理器:
PHP_INI_ENTRY_EX("sample4.greeting", "Hello World", PHP_INI_ALL,
php_sample4_modify_greeting, php_sample4_display_greeting) 顯然, 需要在INI設(shè)置定義之前聲明這個函數(shù). 和OnModify回調(diào)函數(shù)一樣, 這可以通過一個包裝宏以及少量編碼完成:
#include "SAPI.h" /* needed for sapi_module */
PHP_INI_DISP(php_sample4_display_greeting)
{
const char *value = ini_entry->value;
/* 選擇合適的當前值或原始值 */
if (type == ZEND_INI_DISPLAY_ORIG &&
ini_entry->modified) {
value = ini_entry->orig_value;
}
/* 使得打招呼的字符串粗體顯示(當以HTML方式輸出時) */
if (sapi_module.phpinfo_as_text) {
php_printf("%s", value);
} else {
php_printf("<b>%s</b>", value);
}
} 綁定到擴展的全局空間 所有的INI指令都在Zend引擎內(nèi)有一塊存儲空間, 可以用以跟蹤腳本內(nèi)的變更并進行請求外部的全局設(shè)置維護. 在這塊存儲空間中, 所有的INI指令都以字符串值存儲. 你已經(jīng)知道了, 這些值可以使用INI_INT(), INI_FLT(), INI_BOOL()等宏函數(shù), 很簡單的翻譯成其他的標量類型. 這個查找和轉(zhuǎn)換過程由于兩個原因非常低效: 首先, 每次一個INI的值在獲取時, 它必須通過名字在一個HashTable中進行定位. 這種查找方式對于僅在運行時編譯的用戶空間腳本而言是沒有問題的, 但是對于已編譯的機器代碼源, 運行時做這個工作就毫無意義. 每次請求標量值的時候都需要將底層的字符串值轉(zhuǎn)換到標量值是非常低效的. 因此我們使用你已經(jīng)學習過的線程安全全局空間作為存儲媒介, 每次INI指令值變更時更新它即可. 這樣, 所有訪問INI指令的代碼都只需要查找你的線程安全全局空間結(jié)構(gòu)體中的某個指針即可, 這樣就獲得了編譯期優(yōu)化的優(yōu)點. 在你的php_sample4.h文件MODULE_GLOBALS結(jié)構(gòu)體中增加const char *greeting; 接著更新sample4.c中的下面兩個方法: ZEND_INI_MH(php_sample4_modify_greeting)
{
/* Disallow empty greetings */
if (new_value_length == 0) {
return FAILURE;
}
SAMPLE4_G(greeting) = new_value;
return SUCCESS;
}
PHP_FUNCTION(sample4_hello_world)
{
php_printf("%s\n", SAMPLE4_G(greeting));
} 由于這是對INI訪問的一種非常常見的優(yōu)化方式, 因此引擎暴露了一組專門處理INI指令到全局變量的綁定宏: STD_PHP_INI_ENTRY_EX("sample4.greeting", "Hello World",
PHP_INI_ALL, OnUpdateStringUnempty, greeting,
zend_sample4_globals, sample4_globals,
php_sample4_display_greeting)
這個宏執(zhí)行和上面你自己的php_sample4_modify_greeting相同的工作, 但它不需要OnModify回調(diào). 取而代之的是, 它使用了一個泛化的修改回調(diào)OnUpdateStringUnempty, 以及信息應(yīng)該存儲的空間. 如果要允許空的greeting指令值, 你可以直接指定OnUpdateString替代OnUpdateStringUnempty. 類似的, INI指令也可以綁定long, double, zend_bool的標量值. 在你的php_sample4.h中MODULE_GLOBALS結(jié)構(gòu)體上增加幾個字段: long mylong;
double mydouble;
zend_bool mybool; 現(xiàn)在在你的PHP_INI_BEGIN()/PHP_INI_END()代碼塊中使用STD_PHP_INI_ENTRY()宏創(chuàng)建新的INI指令, 它和對應(yīng)的_EX版本的宏的區(qū)別只是顯示處理器以及綁定到的值不同.
STD_PHP_INI_ENTRY("sample4.longval", "123",
PHP_INI_ALL, OnUpdateLong, mylong,
zend_sample4_globals, sample4_globals)
STD_PHP_INI_ENTRY("sample4.doubleval", "123.456",
PHP_INI_ALL, OnUpdateDouble, mydouble,
zend_sample4_globals, sample4_globals)
STD_PHP_INI_ENTRY("sample4.boolval", "1",
PHP_INI_ALL, OnUpdateBool, mybool,
zend_sample4_globals, sample4_globals) 這里要注意, 如果調(diào)用了DISPLAY_INI_ENTRIES(), 布爾類型的INI指令"sample4.boolval"將和其他設(shè)置一樣, 被顯示為它的字符串值; 然而, 首選的布爾值指令應(yīng)該被顯示為"on"或"off". 要使用這些更加表意的顯示, 你可以使用STD_PHP_INI_ENTRY_EX()宏并創(chuàng)建顯示處理器, 或者使用另外一個宏:
STD_PHP_INI_BOOLEAN("sample4.boolval", "1",
PHP_INI_ALL, OnUpdateBool, mybool,
zend_sample4_globals *, sample4_globals)
這個特定類型的宏是布爾類型特有的, 它提供的是將布爾值轉(zhuǎn)換為"on"/"off"值的顯示處理器.
小結(jié)
在本章, 你了解了php語言中最古老的特性之一的實現(xiàn), 它也是阻礙php可移植的罪魁. 對于每個新的INI設(shè)置, 都會使得編寫可移植代碼變得更加復雜. 使用這些特性要非常慎重, 因為擴展以后時鐘都要使用它了. 并且, 在使用時要注意不同系統(tǒng)間的行為一致性, 以免在維護時出現(xiàn)不可預(yù)期的狀況.
接下來的三張, 我們將深入到流API, 開始使用流的實現(xiàn)層和包裝操作, 上下文, 過濾器等.
以上就是[翻譯][php擴展開發(fā)和嵌入式]第13章-php的INI設(shè)置?的內(nèi)容,更多相關(guān)內(nèi)容請關(guān)注PHP中文網(wǎng)(miracleart.cn)!
本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔相應(yīng)的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn
我如何了解最新的PHP開發(fā)和最佳實踐?
Jun 23, 2025 am 12:56 AM
TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource
什麼是PHP,為什麼它用於Web開發(fā)?
Jun 23, 2025 am 12:55 AM
PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti
如何設(shè)置PHP時區(qū)?
Jun 25, 2025 am 01:00 AM
tosetTherightTimeZoneInphp,restate_default_timezone_set()functionAtthestArtofyourscriptWithavalIdidentIdentifiersuchas'america/new_york'.1.usedate_default_default_timezone_set_set()
我如何驗證PHP中的用戶輸入以確保其符合某些標準?
Jun 22, 2025 am 01:00 AM
TovalidateuserinputinPHP,usebuilt-invalidationfunctionslikefilter_var()andfilter_input(),applyregularexpressionsforcustomformatssuchasusernamesorphonenumbers,checkdatatypesfornumericvalueslikeageorprice,setlengthlimitsandtrimwhitespacetopreventlayout
如何將PHP代碼嵌入HTML文件中?
Jun 22, 2025 am 01:00 AM
可以將PHP代碼嵌入HTML文件中,但需確保文件以.php為擴展名,以便服務(wù)器能正確解析。使用標準的標籤包裹PHP代碼,可在HTML中任意位置插入動態(tài)內(nèi)容。此外,可在同一文件中多次切換PHP與HTML,實現(xiàn)條件渲染等動態(tài)功能。務(wù)必注意服務(wù)器配置及語法正確性,避免因短標籤、引號錯誤或遺漏結(jié)束標籤導致問題。
編寫清潔和可維護的PHP代碼的最佳實踐是什麼?
Jun 24, 2025 am 12:53 AM
寫乾淨、易維護的PHP代碼關(guān)鍵在於清晰命名、遵循標準、合理結(jié)構(gòu)、善用註釋和可測試性。 1.使用明確的變量、函數(shù)和類名,如$userData和calculateTotalPrice();2.遵循PSR-12標準統(tǒng)一代碼風格;3.按職責拆分代碼結(jié)構(gòu),使用MVC或Laravel式目錄組織;4.避免麵條式代碼,將邏輯拆分為單一職責的小函數(shù);5.在關(guān)鍵處添加註釋並撰寫接口文檔,明確參數(shù)、返回值和異常;6.提高可測試性,採用依賴注入、減少全局狀態(tài)和靜態(tài)方法。這些做法提升代碼質(zhì)量、協(xié)作效率和後期維護便利性。
如何使用PHP執(zhí)行SQL查詢?
Jun 24, 2025 am 12:54 AM
Yes,youcanrunSQLqueriesusingPHP,andtheprocessinvolveschoosingadatabaseextension,connectingtothedatabase,executingqueriessafely,andclosingconnectionswhendone.Todothis,firstchoosebetweenMySQLiorPDO,withPDObeingmoreflexibleduetosupportingmultipledatabas
See all articles
|
|