Paramètres INI
et les précédents 1 Comme les variables superglobales et les constantes persistantes que vous avez vues au chapitre 1, les valeurs php.ini doivent être définies dans le bloc MINIT étendu. Cependant, contrairement à d'autres fonctionnalités, la définition des options INI se compose uniquement de simples lignes de démarrage/arrêt.
PHP_MINIT_FUNCTION(sample4) { REGISTER_INI_ENTRIES(); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(sample4) { UNREGISTER_INI_ENTRIES(); return SUCCESS; }
Définir et accéder aux paramètres INI
La commande INI elle-même est au-dessus de la fonction MINIT dans la source fichier de code, défini de manière totalement indépendante à l'aide des macros suivantes, une ou plusieurs instructions INI peuvent être définies entre ces deux macros :
PHP_INI_BEIGN() PHP_INI_END()
Ces deux fonctions de macro sont similaires à ZEND_BEGIN_MODULE_GLOBALS()/ZEND_END_MODULE_GLOBALS() Cependant, il ne s'agit pas d'une structure typdef, mais d'une organisation-cadre pour la définition d'instances de données statiques :
<. 🎜>static zend_ini_entry ini_entries[] = { {0,0,NULL,0,NULL,NULL,NULL,NULL,NULL,0,NULL,0,0,NULL} };
Comme vous pouvez le voir, il définit un vecteur de valeurs zend_ini_entry, se terminant par un enregistrement vide. C'est la même chose que. vous feriez La définition du vecteur statique function_entry vue plus tôt est cohérente.
Paramètres INI simples
Maintenant, vous have Il existe une structure INI utilisée pour définir les instructions INI, ainsi que le mécanisme permettant au moteur d'enregistrer/désinstaller les paramètres INI, afin que nous puissions réellement définir certaines instructions INI pour votre extension. Supposons que votre extension expose une fonction de message d'accueil, comme Identique à. au chapitre 5 "Votre première extension", vous pouvez cependant la personnaliser si vous souhaitez lui dire bonjour :
PHP_FUNCTION(sample4_hello_world) { php_printf("Hello World!\n"); }
La manière la plus simple et la plus directe est de définir une commande INI, et donnez-lui la valeur par défaut "Bonjour tout le monde !" :
#include "php_ini.h" PHP_INI_BEGIN() PHP_INI_ENTRY("sample4.greeting", "Hello World", PHP_INI_ALL, NULL) PHP_INI_END()
Vous avez peut-être Je l'ai deviné, les deux premiers paramètres de cette macro représentent le nom de l'instruction INI et sa valeur par défaut. Le troisième paramètre est utilisé pour déterminer si le moteur autorise la modification de l'instruction INI (cela impliquera d'introduire le problème du niveau d'accès). plus loin dans ce chapitre) . Le dernier paramètre est une fonction de rappel qui sera appelée à chaque fois que la valeur de l'instruction INI change. Vous verrez les détails de ce paramètre dans la section Modifier les événements. Remarque sur la traduction : si vous, comme le traducteur, rencontrez des résultats incompatibles avec les résultats attendus du travail original, veuillez ajouter un appel "REGISTER_INI_ENTRIES();" à votre fonction MINIT() pendant le test, et assurez-vous que l'appel est dans votre exécution après avoir alloué un espace global dans MINIT.
Maintenant que vos paramètres INI ont été définis, il ne vous reste plus qu'à l'utiliser dans votre fonction d'accueil .
Assurez-vous de noter que la valeur de char * appartient au moteur et ne doit pas être modifiée. Pour cette raison, définissez votre variable locale utilisée pour stocker temporairement le. INI définissant la valeur comme const Bien sûr, toutes les valeurs INI ne sont pas des chaînes ; il existe d'autres macros pour obtenir des valeurs entières, à virgule flottante et booléennes :
PHP_FUNCTION(sample4_hello_world) { const char *greeting = INI_STR("sample4.greeting"); php_printf("%s\n", greeting); }
long lval = INI_INT("sample4.intval"); double dval = INI_FLT("sample4.fltval"); zend_bool bval = INI_BOOL("sample4.boolval");
Dans cet exemple, le nom de l'instruction INI "sample4.greeting" est préfixé par une extension pour garantir qu'elle n'entrera pas en conflit avec les noms d'instructions INI exposés par d'autres extensions privées. ce préfixe n'est pas obligatoire, mais est encouragé pour les extensions publiques pour les versions commerciales ou open source
Niveau d'accès
.Pour les instructions INI, il existe toujours une valeur par défaut avec laquelle commencer. Dans la plupart des cas, l'idéal est de laisser la valeur par défaut inchangée. Cependant, pour certaines circonstances particulières ou actions spécifiques au sein du script, ces valeurs peut Doit être modifié. Comme le montre le tableau ci-dessous, la valeur de l'instruction INI peut être modifiée aux trois points suivants :
Niveau d'accès | Signification |
SYSTÈME | se trouve dans php.ini , ou apache de httpd.conf fichier de configuration |
PERDIR | se trouve dans le fichier de configuration httpd.conf d'Apache > |
UTILISATEUR | Une fois que le script commence à s'exécuter , ne peut être modifié qu'en appelant la fonction de l'espace utilisateur ini_set( ) INI ensembles . |
参数名 | 含义 |
entry | pointe vers l'élément de commande INI réellement stocké par le moteur.Cette structure fournit Valeur actuelle , Valeur d'origine , module auquel il appartient , et quelques autres codes ci-dessous (zend_ini_entrystructure structure)Informations répertoriées |
new_value | La valeur à définir.Si le processeur renvoie SUCCÈS,Cette valeur sera définie sur entrée->valeur, et si entrée-> orig_value n'a actuellement pas défini, définira la valeur actuelle sur entry->orig_value dans , et définissez la balise entry->modified .La longueur de ce la chaîne est passée new_value_lengthpassing. |
mh_arg1, 2, 3 | Ces 3 pointeurs correspondent aux pointeurs de données donnés lorsque l'instruction INI est défini (zend_ini_entry3 membres portant le même nom ).en fait ,Ces valeurs sont utilisées par le moteur pour le traitement interne,Vous n'avez pas besoin de vous en soucier. |
scène | ZEND_INI_STAGE_ série Une des 5 valeurs : STARTUP, SHUTDOWN, ACTIVATE, DEACTIVATE, RUNTIME Ces constantes correspondent à MINIT, MSHUTDOWN, RINIT, RSHUTDOWN, et à l'exécution du script actif . |
核心结构体: 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设置
在上一章, 你看到了MINFO函数以及相关的指令用于展示扩展的信息. 由于扩展暴露INI指令是很常见的, 因此引擎提供了一个公共的宏可以放置到PHP_MINFO_FUNCTION()中用于展示INI指令信息.
PHP_MINFO_FUNCTION(sample4) { DISPLAY_INI_ENTRIES(); }
这个宏将迭代PHP_INI_BEGIN()和PHP_INI_END()宏之间定义的INI指令集和, 在一个3列的表格中展示它们的INI指令名, 原始值(全局的), 以及当前值(经过PERDIR指令或ini_set()调用修改后)
默认情况下, 所有的指令都直接以其字符串形式输出. 对于某些指令, 比如布尔值以及用于语法高亮的颜色值, 则在展示处理时应用了其他格式. 这些格式是通过每个INI设置的显示处理器处理的, 它和你看到的OnModify一样是一个动态的回调函数指针.
显示处理器可以使用PHP_INI_ENTRY()宏的扩展版指定, 它接受一个额外的参数. 如果设置为NULL, 则使用展示字符串值的处理器作为默认处理器:
PHP_INI_ENTRY_EX("sample4.greeting", "Hello World", PHP_INI_ALL, php_sample4_modify_greeting, php_sample4_display_greeting)
显然, 需要在INI设置定义之前声明这个函数. 和OnModify回调函数一样, 这可以通过一个包装宏以及少量编码完成:
#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引擎内有一块存储空间, 可以用以跟踪脚本内的变更并进行请求外部的全局设置维护. 在这块存储空间中, 所有的INI指令都以字符串值存储. 你已经知道了, 这些值可以使用INI_INT(), INI_FLT(), INI_BOOL()等宏函数, 很简单的翻译成其他的标量类型.
这个查找和转换过程由于两个原因非常低效: 首先, 每次一个INI的值在获取时, 它必须通过名字在一个HashTable中进行定位. 这种查找方式对于仅在运行时编译的用户空间脚本而言是没有问题的, 但是对于已编译的机器代码源, 运行时做这个工作就毫无意义.
每次请求标量值的时候都需要将底层的字符串值转换到标量值是非常低效的. 因此我们使用你已经学习过的线程安全全局空间作为存储媒介, 每次INI指令值变更时更新它即可. 这样, 所有访问INI指令的代码都只需要查找你的线程安全全局空间结构体中的某个指针即可, 这样就获得了编译期优化的优点.
在你的php_sample4.h文件MODULE_GLOBALS结构体中增加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访问的一种非常常见的优化方式, 因此引擎暴露了一组专门处理INI指令到全局变量的绑定宏:
STD_PHP_INI_ENTRY_EX("sample4.greeting", "Hello World", PHP_INI_ALL, OnUpdateStringUnempty, greeting, zend_sample4_globals, sample4_globals, php_sample4_display_greeting)
这个宏执行和上面你自己的php_sample4_modify_greeting相同的工作, 但它不需要OnModify回调. 取而代之的是, 它使用了一个泛化的修改回调OnUpdateStringUnempty, 以及信息应该存储的空间. 如果要允许空的greeting指令值, 你可以直接指定OnUpdateString替代OnUpdateStringUnempty.
类似的, INI指令也可以绑定long, double, zend_bool的标量值. 在你的php_sample4.h中MODULE_GLOBALS结构体上增加几个字段:
long mylong; double mydouble; zend_bool mybool;
现在在你的PHP_INI_BEGIN()/PHP_INI_END()代码块中使用STD_PHP_INI_ENTRY()宏创建新的INI指令, 它和对应的_EX版本的宏的区别只是显示处理器以及绑定到的值不同.
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)
这里要注意, 如果调用了DISPLAY_INI_ENTRIES(), 布尔类型的INI指令"sample4.boolval"将和其他设置一样, 被显示为它的字符串值; 然而, 首选的布尔值指令应该被显示为"on"或"off". 要使用这些更加表意的显示, 你可以使用STD_PHP_INI_ENTRY_EX()宏并创建显示处理器, 或者使用另外一个宏:
STD_PHP_INI_BOOLEAN("sample4.boolval", "1", PHP_INI_ALL, OnUpdateBool, mybool, zend_sample4_globals *, sample4_globals)
这个特定类型的宏是布尔类型特有的, 它提供的是将布尔值转换为"on"/"off"值的显示处理器.
小结
在本章, 你了解了php语言中最古老的特性之一的实现, 它也是阻碍php可移植的罪魁. 对于每个新的INI设置, 都会使得编写可移植代码变得更加复杂. 使用这些特性要非常慎重, 因为扩展以后时钟都要使用它了. 并且, 在使用时要注意不同系统间的行为一致性, 以免在维护时出现不可预期的状况.
接下来的三张, 我们将深入到流API, 开始使用流的实现层和包装操作, 上下文, 过滤器等.
以上就是[翻译][php扩展开发和嵌入式]第13章-php的INI设置 的内容,更多相关内容请关注PHP中文网(www.php.cn)!