Bab ini merinci bagaimana PHP bermain dengan konfigurasinya dan bagaimana ekstensi diharapkan terhubung ke langkah konfigurasi utama PHP, dengan mendaftar dan memanfaatkan pengaturan INI
Validator dan jembatan memori global
Sejauh ini bagus, mendaftar dan membaca kembali nilai pengaturan INI tidak terlalu sulit. Tapi cara kami menggunakannya di baris sebelumnya di atas jauh dari optimal
Ada dua masalah yang akan diselesaikan pada saat yang sama dengan menggunakan API pengaturan INI 'lanjutan'
Setiap kali kita ingin membaca nilai kita, diperlukan pencarian ke tabel pengaturan INI utama, serta pemeran ke tipe yang tepat [seringkali]. Operasi tersebut menghabiskan beberapa siklus CPU
Kami tidak menyediakan validator apa pun, sehingga pengguna dapat mengubah pengaturan kami dan memasukkan apa pun yang dia inginkan sebagai nilai
Solusinya adalah dengan menggunakan on_modify[]
validator dan jembatan memori untuk memperbarui variabel global
Dengan menggunakan API manajemen pengaturan INI lanjutan, kita dapat memberi tahu mesin untuk mendaftarkan pengaturan kita secara normal, tetapi kita juga dapat menginstruksikannya untuk memperbarui global selera kita setiap kali nilai pengaturan INI diubah. Karenanya, kapan pun kita ingin membaca kembali nilai kita, kita hanya perlu membaca global kita. Ini akan memberikan peningkatan kinerja jika kita perlu sering membaca nilai pengaturan INI, karena pencarian hashtable dan operasi pemeran tidak diperlukan lagi
Catatan
Anda harus merasa nyaman dengan global untuk melanjutkan membaca bab ini. Manajemen ruang global diperlakukan ke dalam babnya sendiri
Untuk mendeklarasikan jembatan memori ke global, kita perlu membuat permintaan global, dan mengubah cara pengaturan INI dideklarasikan. Seperti ini
ZEND_BEGIN_MODULE_GLOBALS[pib] zend_ulong max_rnd; ZEND_END_MODULE_GLOBALS[pib] ZEND_DECLARE_MODULE_GLOBALS[pib] PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, OnUpdateLongGEZero, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[] PHP_MINIT_FUNCTION[pib] { REGISTER_INI_ENTRIES[]; return SUCCESS; }
Kami mendeklarasikan nama global max_rnd
, jenis zend_ulong
. Kemudian, kami mendaftarkan 'pib. nilai rand_max’ IN menggunakan ________ 54 _______ kali ini. Itu memungkinkan kita untuk meneruskan lebih banyak parameter ke makro. Tiga yang pertama diketahui, kami merincinya sebelumnya di bab ini
Empat parameter terakhir mewakili jembatan global. Kami memberi tahu bahwa kami ingin memperbarui max_rnd
, dalam struktur
php_printf["The value is : %lu", PIB_G[max_rnd]];1 yang diwakili oleh simbol
php_printf["The value is : %lu", PIB_G[max_rnd]];2. Baca bab manajemen global jika tidak nyaman. Sebagai pengingat cepat,
php_printf["The value is : %lu", PIB_G[max_rnd]];3 menyatakan
php_printf["The value is : %lu", PIB_G[max_rnd]];1 struktur, dan
php_printf["The value is : %lu", PIB_G[max_rnd]];5 menyatakan
php_printf["The value is : %lu", PIB_G[max_rnd]];2 simbol dari jenis tersebut
Catatan
Secara internal, offsetof akan digunakan untuk menghitung potongan byte dari anggota max_rnd
kami ke dalam struktur
php_printf["The value is : %lu", PIB_G[max_rnd]];1, untuk dapat memperbarui bagian memori tersebut setiap kali 'pib. rnd_max' akan diubah
Validator on_modify[]
yang digunakan di sini,
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }0, adalah validator default yang ada di PHP dan memvalidasi nilai dengan panjang lebih besar dari atau sama dengan nol. Validator diperlukan agar global diperbarui, karena pekerjaan seperti itu dilakukan ke validator
Sekarang, untuk membaca kembali nilai pengaturan INI kita, kita hanya perlu membaca nilai max_rnd
global kita
php_printf["The value is : %lu", PIB_G[max_rnd]];_
Dan kita selesai
Mari kita lihat validator sekarang [on_modify[]
handler]. Validator memiliki dua tujuan
Validasi nilai yang diteruskan
Perbarui global jika validasi berhasil
Validator hanya dipanggil saat pengaturan INI disetel atau diubah [ditulis ke], setiap kali langkah ini terjadi
Peringatan
Jika Anda ingin variabel global diperbarui dengan nilai pengaturan INI, Anda memerlukan validator. Mekanisme seperti itu tidak secara ajaib dilakukan oleh mesin, tetapi harus dilakukan secara eksplisit ke dalam validator
Mari kita lihat kode sumber
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }_0
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }_
Seperti yang Anda lihat, tidak ada yang rumit. Validator Anda diberi
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }4 dan harus memvalidasinya. Ingatlah bahwa
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }_4 bertipe zend_string *.
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }0 mengambil nilai selama dan memeriksa apakah itu bilangan bulat positif. Seseorang harus mengembalikan
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }_7 dari validator jika semuanya berjalan dengan baik dan
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }8 jika tidak
Kemudian muncul bagian untuk memperbarui global.
#define ZEND_INI_MH[name] int name[zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage] ZEND_API ZEND_INI_MH[OnUpdateLongGEZero] { zend_long *p, tmp; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0] { return FAILURE; } p = [zend_long *] [base+[size_t] mh_arg1]; *p = tmp; return SUCCESS; }_9 variabel digunakan untuk membawa semua jenis informasi ke validator Anda
Catatan
'mh' adalah singkatan dari modif handler. Callback validator juga disebut callback handler modifikasi
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]0 adalah pointer ke area memori yang mewakili awal memori struktur global Anda, dalam kasus kami, awal dari
php_printf["The value is : %lu", PIB_G[max_rnd]];2 memori yang dialokasikan. Perhatikan bahwa ketika kita berbicara tentang memori variabel global-permintaan, yang terakhir diakses secara berbeda jika Anda menggunakan mode ZTS atau tidak. Informasi lebih lanjut tentang ZTS dapat ditemukan di sini
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]_2 diberikan offset yang dihitung dari anggota global Anda [
max_rnd
untuk kami], dan Anda harus mengiris memori sendiri untuk mendapatkan pointer ke sana. Itu sebabnya kami menyimpan ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]_0 sebagai pointer
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]5 umum dan mentransmisikan
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]2 ke
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]7
Kemudian, Anda cukup memperbarui konten dengan nilai yang divalidasi dengan menulis ke penunjuk.
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]_8 sebenarnya tidak digunakan
Validator default dari PHP adalah
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]9,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */0,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */1,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */2,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */3, dan
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */4. Nama mereka menggambarkan diri sendiri dan kode sumbernya juga [Anda dapat membacanya]
Berdasarkan model seperti itu, kita dapat mengembangkan validator kita sendiri, yang memvalidasi terhadap bilangan bulat positif antara 0 dan 1000 misalnya
ZEND_INI_MH[onUpdateMaxRnd] { zend_long tmp; zend_long *p; #ifndef ZTS char *base = [char *] mh_arg2; #else char *base; base = [char *] ts_resource[*[[int *] mh_arg2]]; #endif p = [zend_long *] [base+[size_t] mh_arg1]; tmp = zend_atol[ZSTR_VAL[new_value], [int]ZSTR_LEN[new_value]]; if [tmp < 0 || tmp > 1000] { return FAILURE; } *p = tmp; return SUCCESS; } PHP_INI_BEGIN[] STD_PHP_INI_ENTRY["pib.rnd_max", "100", PHP_INI_ALL, onUpdateMaxRnd, max_rnd, zend_pib_globals, pib_globals] PHP_INI_END[]
Catatan
Aman untuk menulis ke long yang tidak ditandatangani dari long, segera setelah rentang diperiksa, yang dilakukan oleh validator
Sekarang, jika pengguna ingin mengubah pengaturan dan memberikan nilai yang salah yang tidak divalidasi,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */5 hanya akan mengembalikan false ke tanah pengguna, dan tidak akan mengubah nilai
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */Dalam kasus sebaliknya,
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */_5 mengembalikan nilai lama dan mengubah nilai saat ini. Nilai baru yang diberikan menjadi
nilai "lokal" saat ini sedangkan nilai default sebelumnya tetap sebagai "nilai master".
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */_7 atau
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */8 merinci nilai-nilai tersebut. Contoh
ini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */
Harap diperhatikan bahwa panggilan balik validator Anda akan dipanggil setiap kali nilai diubah, dan diubah beberapa kali. Misalnya, untuk contoh kecil kami, validator yang kami rancang dipanggil tiga kali
Sekali di
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */
_9, diini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */
0. Kami menetapkan nilai default ke pengaturan kami di sini, maka ini dilakukan dengan menggunakan validator kami. Ingatlah bahwa nilai default dapat berasal dari parsing file INISekali per
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */
_5 panggilan penggunaSekali dalam
ini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */
_2, ketika mesin akan berusaha mengembalikan nilai lokal ke nilai masternya, jika nilai telah diubah selama permintaan saat ini. Userlandini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */
_3 melakukan pekerjaan yang sama
Ingatlah juga bahwa pengakses nilai diperiksa oleh
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */5. Jika kami akan merancang pengaturan
ini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */5, maka pengguna tidak akan dapat memodifikasinya menggunakan
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */5, karena
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */5 menggunakan
ini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */8 sebagai pengakses. Ketidaksesuaian kemudian akan terdeteksi dan validator tidak akan dipanggil oleh mesin dalam kasus seperti itu
Jika Anda perlu mengubah nilai pengaturan INI menjadi ekstensi Anda saat runtime, panggilan internal adalah
ini_set['pib.rnd_max', 500]; var_dump[ini_get_all['pib']]; /* array[1] { ["pib.rnd_max"]=> array[3] { ["global_value"]=> string[3] "100" ["local_value"]=> string[3] "500" ["access"]=> int[7] } */9, inilah yang digunakan oleh userland
ini_set['pib.rnd_max', 2048]; /* returns false as 2048 is > 1000 */5