Following previous article let’s talk about the php life cycle and see which hooks are extended to do what, php There are about 5 stages in the life cycle, module initialization stagephp_module_startup
, request initialization stagephp_request_startup
, script execution stagephp_execute_script
, request shutdown stagephp_request_shutdown
,Module shutdown phasephp_module_shutdown
, introduced below in cli mode.
php_module_startup
First take a look at what is done at this stage. If you don’t know where the php entry file is, use gdb to look at the call stack, gdb ./ php
At the php_module_startup
break point, execute, look at the call stack,
1 2 3 4 5 6 7 8 9 10 11 | b php_module_startup
(gdb) r test.php
bt
php_module_startup (sf=0x1406460 <cli_sapi_module>,
additional_modules=0x0, num_additional_modules=0)
at /www/test/php/php-7.4.3/main/main.c:2098
#1 0x00000000008bae7c in php_cli_startup (
sapi_module=0x1406460 <cli_sapi_module>)
at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:407
#2 0x00000000008bcc80 in main (argc=2, argv=0x1425af0)
at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:1323
|
Copy after login
You can clearly see the execution process in the call stack, now go to/ main/main.c file to see what has been done. You can also use gdb to see it step by step. Here are a few places related to PHP extensions. The initialization work done here, such as garbage collection, request initialization, and registered constants. php.ini configuration file loading, etc.
Let’s first look at how to load the module
1 2 3 4 5 | if (php_register_internal_extensions_func() == FAILURE) {
php_printf( "Unable to start builtin modules\n" );
return FAILURE;
}
|
Copy after login
Here is to load the built-in module of php. Only the core functions are posted here. Check the dependencies first
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | if (module->deps) {
const zend_module_dep *dep = module->deps;
while (dep->name) {
if (dep->type == MODULE_DEP_CONFLICTS) {
name_len = strlen (dep->name);
lcname = zend_string_alloc(name_len, 0);
zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
zend_string_efree(lcname);
zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded" , module->name, dep->name);
return NULL;
}
zend_string_efree(lcname);
}
++dep;
}
}
|
Copy after login
1 2 3 4 5 6 7 | if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
zend_hash_del(&module_registry, lcname);
zend_string_release(lcname);
EG(current_module) = NULL;
zend_error(E_CORE_WARNING, "%s: Unable to register functions, unable to load" , module->name);
return NULL;
}
|
Copy after login
This is the principle of loading built-in modules. Now let’s see how to load the extension in ini
1 | php_ini_register_extensions();
|
Copy after login
1 | zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb);
|
Copy after login
Use this function to load
1 | php_load_extension(char *filename, int type, int start_now)
|
Copy after login
This also performs the function of loading built-in modules.
is calling module->functions
to register the module function function. Now we know why the function function should be written in helloworld_functions
here
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | zend_module_entry helloworld_module_entry = {
STANDARD_MODULE_HEADER,
"helloworld" ,
helloworld_functions,
PHP_MINIT(helloworld),
NULL,
PHP_RINIT(helloworld),
NULL,
PHP_MINFO(helloworld),
PHP_HELLOWORLD_VERSION,
PHP_MODULE_GLOBALS(pib),
NULL,
NULL,
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
|
Copy after login
Now look at several hook functions of the extension
1 2 | zend_startup_extensions();
|
Copy after login
The core here isfunc(element->data)
That is, executing the extension
PHP_MINIT
Function
1 2 3 4 5 6 7 8 | element=l->head;
while (element) {
next = element->next;
if (func(element->data)) {
DEL_LLIST_ELEMENT(element, l);
}
element = next;
}
|
Copy after login
Now we know thatPHP_MINIT
The hook can do many initialization functions. How to register a custom extended function class and how to write the extended variables into php.ini , how to rewrite php built-in functions,
1 2 3 4 5 6 7 8 9 10 | original = zend_hash_str_find_ptr(CG(function_table), "var_dump" , sizeof( "var_dump" )-1);
if (original != NULL) {
original->internal_function.handler = my_overwrite_var_dump;
}
zend_class_entry person;
INIT_CLASS_ENTRY(person,CLASS_NAME,person_functions);
zend_register_internal_class_ex(&person,NULL);
|
Copy after login
Here is to rewrite the var_dump function, register a person class, introduce it here first, Next article will introduce how to pass php code through lexical analysis Syntax analysis generates AST, and then compiles opcode instructions for call by zend virtual machine.
Recommended learning: "PHP Video Tutorial"
The above is the detailed content of How to customize PHP extension (2) hook function. For more information, please follow other related articles on the PHP Chinese website!