<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 7.4 鉤子函數 PHP為擴展提供了5個鉤子函數,PHP執行到不同階段時回調各個擴展定義的鉤子函數,擴展可以通過這些鉤子函數介入到PHP生命周期的不同階段中去,這些鉤子函數的定義非常簡單,PHP提供了對應的宏,定義完成后只需要設置`zend_module_entry`對應的函數指針即可。 前面已經介紹過PHP生命周期的幾個階段,這幾個鉤子函數執行的先后順序:module startup -> request startup -> 編譯、執行 -> request shutdown -> post deactivate -> module shutdown。 ### 7.4.1 module_startup_func 這個函數在PHP模塊初始化階段執行,通常情況下,此過程只會在SAPI啟動后執行一次。這個階段可以進行內部類的注冊,如果你的擴展提供了類就可以在此函數中完成注冊;除了類還可以在此函數中注冊擴展定義的常量;另外,擴展可以在此階段覆蓋PHP編譯、執行的兩個函數指針:zend_compile_file、zend_execute_ex,從而可以接管PHP的編譯、執行,opcache的實現原理就是替換了zend_compile_file,從而使得PHP編譯時調用的是opcache自己定義的編譯函數,對編譯后的結果進行緩存。 此鉤子函數通過`PHP_MINIT_FUNCTION()`或`ZEND_MINIT_FUNCTION()`宏完成定義: ```c PHP_MINIT_FUNCTION(extension_name) { ... } ``` 展開后: ```c zm_startup_extension_name(int type, int module_number) { ... } ``` 最后通過`PHP_MINIT()`或`ZEND_MINIT()`宏將zend_module_entry的module_startup_func設置為上面定義的函數。 ```c #define PHP_MINIT ZEND_MODULE_STARTUP_N #define ZEND_MINIT ZEND_MODULE_STARTUP_N #define ZEND_MODULE_STARTUP_N(module) zm_startup_##module ``` ### 7.4.2 request_startup_func 此函數在編譯、執行之前回調,fpm模式下每一個http請求就是一個request,腳本執行前將首先執行這個函數。如果你的擴展需要針對每一個請求進行處理則可以設置這個函數,如:對請求進行filter、根據請求ip獲取所在城市、對請求/返回數據加解密等。此函數通過`PHP_RINIT_FUNCTION()`或`ZEND_RINIT_FUNCTION()`宏定義: ```c PHP_RINIT_FUNCTION(extension_name) { ... } ``` 展開后: ```c zm_activate_extension_name(int type, int module_number) { ... } ``` 獲取函數地址的宏:`PHP_RINIT()`或`ZEND_RINIT()`: ```c #define PHP_RINIT ZEND_MODULE_ACTIVATE_N #define ZEND_RINIT ZEND_MODULE_ACTIVATE_N #define ZEND_MODULE_ACTIVATE_N(module) zm_activate_##module ``` ### 7.4.3 request_shutdown_func 此函數在請求結束時被調用,通過`PHP_RSHUTDOWN_FUNCTION()`或`ZEND_RSHUTDOWN_FUNCTION()`宏定義: ```c PHP_RSHUTDOWN_FUNCTION(extension_name) { ... } ``` 函數地址通過`PHP_RSHUTDOWN()`或`ZEND_RSHUTDOWN()`獲取: ```c #define PHP_RSHUTDOWN ZEND_MODULE_DEACTIVATE_N #define ZEND_RSHUTDOWN ZEND_MODULE_DEACTIVATE_N #define ZEND_MODULE_DEACTIVATE_N(module) zm_deactivate_##module ``` ### 7.4.4 post_deactivate_func 這個函數比較特殊,一般很少會用到,實際它也是在請求結束之后調用的,它比request_shutdown_func更晚執行: ```c void php_request_shutdown(void *dummy) { ... //調用各擴展的request_shutdown_func if (PG(modules_activated)) { zend_deactivate_modules(); } //關閉輸出:發送http header php_output_deactivate(); //釋放超全局變量:$_GET、$_POST... ... //關閉編譯器、執行器 zend_deactivate(); //調用每個擴展的post_deactivate_func zend_post_deactivate_modules(); ... } ``` 從上面的執行順序可以看出,request_shutdown_func、post_deactivate_func是先后執行的,此函數通過`ZEND_MODULE_POST_ZEND_DEACTIVATE_D()`宏定義,`ZEND_MODULE_POST_ZEND_DEACTIVATE_N()`獲取函數地址: ```c #define ZEND_MINIT ZEND_MODULE_STARTUP_N #define ZEND_MODULE_POST_ZEND_DEACTIVATE_N(module) zm_post_zend_deactivate_##module ``` ### 7.4.5 module_shutdown_func 模塊關閉階段回調的函數,與module_startup_func對應,此階段主要可以進行一些資源的清理,通過`PHP_MSHUTDOWN_FUNCTION()`或`ZEND_MSHUTDOWN_FUNCTION()`定義: ```c PHP_MSHUTDOWN_FUNCTION(extension_name) { ... } ``` 通過`PHP_MSHUTDOWN()`或`ZEND_MSHUTDOWN()`獲取函數地址: ```c #define PHP_MSHUTDOWN ZEND_MODULE_SHUTDOWN_N #define ZEND_MSHUTDOWN ZEND_MODULE_SHUTDOWN_N #define ZEND_MODULE_SHUTDOWN_N(module) zm_shutdown_##module ``` 7.4.6 小節 上面詳細介紹了各個階段定義的鉤子函數的格式,使用gdb調試擴展時可以根據展開后實際的函數名稱設置斷點。這些鉤子實際已經為擴展構造了一個整體的框架,通過這幾個鉤子擴展已經能實現很多功能了,后面我們介紹的很多內容都是在這幾個函數中完成的,比如內部類的注冊、常量注冊、資源注冊等。如果擴展名稱為mytest,則最終定義的擴展: ```c PHP_MINIT_FUNCTION(mytest) { ... } PHP_RINIT_FUNCTION(mytest) { ... } PHP_RSHUTDOWN_FUNCTION(mytest) { ... } PHP_MSHUTDOWN_FUNCTION(mytest) { ... } zend_module_entry mytest_module_entry = { STANDARD_MODULE_HEADER, "mytest", NULL, //mytest_functions, PHP_MINIT(mytest), PHP_MSHUTDOWN(mytest), PHP_RINIT(mytest), PHP_RSHUTDOWN(mytest), NULL, //PHP_MINFO(mytest), "1.0.0", STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE(mytest) ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看