您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關(guān)怎么在PHP中使用register_shutdown_function函數(shù),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
1. 函數(shù)說(shuō)明
定義:該函數(shù)是來(lái)注冊(cè)一個(gè)會(huì)在PHP中止時(shí)執(zhí)行的函數(shù)
參數(shù)說(shuō)明:
void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )
注冊(cè)一個(gè) callback ,它會(huì)在腳本執(zhí)行完成或者 exit() 后被調(diào)用。
callback:待注冊(cè)的中止回調(diào)
parameter:可以通過(guò)傳入額外的參數(shù)來(lái)將參數(shù)傳給中止函數(shù)
2. PHP中止的情況
PHP中止的情況有三種:
執(zhí)行完成
exit/die導(dǎo)致的中止
發(fā)生致命錯(cuò)誤中止
a. 第一種情況,執(zhí)行完成
<?php function test() { echo '這個(gè)是中止方法test的輸出'; } register_shutdown_function('test'); echo 'before' . PHP_EOL;
運(yùn)行:
before 這個(gè)是中止方法test的輸出
注意:輸出的順序,等執(zhí)行完成了之后才會(huì)去執(zhí)行register_shutdown_function的中止方法test
b. 第二種情況,exit/die導(dǎo)致的中止
<?php function test() { echo '這個(gè)是中止方法test的輸出'; } register_shutdown_function('test'); echo 'before' . PHP_EOL; exit(); echo 'after' . PHP_EOL;
運(yùn)行:
before 這個(gè)是中止方法test的輸出
后面的after并沒(méi)有輸出,即exit或者是die方法導(dǎo)致提前中止。
c. 第三種情況,發(fā)送致命錯(cuò)誤中止
<?php function test() { echo '這個(gè)是中止方法test的輸出'; } register_shutdown_function('test'); echo 'before' . PHP_EOL; // 這里會(huì)發(fā)生致命錯(cuò)誤 $a = new a(); echo 'after' . PHP_EOL;
運(yùn)行:
before Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12 Error: Class 'a' not found in D:\laragon\www\php_book\test.php on line 12 Call Stack: 0.0020 360760 1. {main}() D:\laragon\www\php_book\test.php:0 這個(gè)是中止方法test的輸出
后面的after也是沒(méi)有輸出,致命錯(cuò)誤導(dǎo)致提前中止了。
3. 參數(shù)
第一個(gè)參數(shù)支持以數(shù)組的形式來(lái)調(diào)用類(lèi)中的方法,第二個(gè)以及后面的參數(shù)都是可以當(dāng)做額外的參數(shù)傳給中止方法。
<?php class Shutdown { public function stop() { echo "這個(gè)是stop方法的輸出"; } } // 當(dāng)PHP終止的時(shí)候(執(zhí)行完成或者是遇到致命錯(cuò)誤中止的時(shí)候)會(huì)調(diào)用new Shutdown的stop方法 register_shutdown_function([new Shutdown(), 'stop']); // 將因?yàn)橹旅e(cuò)誤而中止 $a = new a(); // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出 echo '必須終止';
也可以在類(lèi)中執(zhí)行:
<?php class TestDemo { public function __construct() { register_shutdown_function([$this, "f"], "hello"); } public function f($str) { echo "class TestDemo->f():" . $str; } } $demo = new TestDemo(); echo 'before' . PHP_EOL; /** 運(yùn)行: before class TestDemo->f():hello */
4. 同時(shí)調(diào)用多個(gè)
可以多次調(diào)用 register_shutdown_function,這些被注冊(cè)的回調(diào)會(huì)按照他們注冊(cè)時(shí)的順序被依次調(diào)用。
不過(guò)注意的是,如果在第一個(gè)注冊(cè)的中止方法里面調(diào)用exit方法或者是die方法的話,那么其他注冊(cè)的中止回調(diào)也不會(huì)被調(diào)用。
代碼:
<?php /** * 可以多次調(diào)用 register_shutdown_function,這些被注冊(cè)的回調(diào)會(huì)按照他們注冊(cè)時(shí)的順序被依次調(diào)用。 * 注意:如果你在f方法(第一個(gè)注冊(cè)的方法)里面調(diào)用exit方法或者是die方法的話,那么其他注冊(cè)的中止回調(diào)也不會(huì)被調(diào)用 */ /** * @param $str */ function f($str) { echo $str . PHP_EOL; // 如果下面調(diào)用exit方法或者是die方法的話,其他注冊(cè)的中止回調(diào)不會(huì)被調(diào)用 // exit(); } // 注冊(cè)第一個(gè)中止回調(diào)f方法 register_shutdown_function("f", "hello"); class TestDemo { public function __construct() { register_shutdown_function([$this, "f"], "hello"); } public function f($str) { echo "class TestDemo->f():" . $str; } } $demo = new TestDemo(); echo 'before' . PHP_EOL; /** 運(yùn)行: before hello class TestDemo->f():hello 注意:如果f方法里面調(diào)用了exit或者是die的話,那么最后的class TestDemo->f():hello不會(huì)輸出 */
5. 用處
該函數(shù)的作用:
析構(gòu)函數(shù):在PHP4的時(shí)候,由于類(lèi)不支持析構(gòu)函數(shù),所以這個(gè)函數(shù)經(jīng)常用來(lái)模擬實(shí)現(xiàn)析構(gòu)函數(shù)
致命錯(cuò)誤的處理:使用該函數(shù)可以用來(lái)捕獲致命錯(cuò)誤并且在發(fā)生致命錯(cuò)誤后恢復(fù)流程處理
代碼如下:
<?php /** * register_shutdown_function,注冊(cè)一個(gè)會(huì)在php中止時(shí)執(zhí)行的函數(shù),中止的情況包括發(fā)生致命錯(cuò)誤、die之后、exit之后、執(zhí)行完成之后都會(huì)調(diào)用register_shutdown_function里面的函數(shù) * Created by PhpStorm. * User: Administrator * Date: 2017/7/15 * Time: 17:41 */ class Shutdown { public function stop() { echo 'Begin.' . PHP_EOL; // 如果有發(fā)生錯(cuò)誤(所有的錯(cuò)誤,包括致命和非致命)的話,獲取最后發(fā)生的錯(cuò)誤 if (error_get_last()) { print_r(error_get_last()); } // ToDo:發(fā)生致命錯(cuò)誤后恢復(fù)流程處理 // 中止后面的所有處理 die('Stop.'); } } // 當(dāng)PHP終止的時(shí)候(執(zhí)行完成或者是遇到致命錯(cuò)誤中止的時(shí)候)會(huì)調(diào)用new Shutdown的stop方法 register_shutdown_function([new Shutdown(), 'stop']); // 將因?yàn)橹旅e(cuò)誤而中止 $a = new a(); // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出 echo '必須終止';
運(yùn)行:
Fatal error: Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31 Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php on line 31 Call Stack: 0.0060 362712 1. {main}() D:\laragon\www\php_book\1_23_register_shutdown.php:0 Begin. Array ( [type] => 1 [message] => Uncaught Error: Class 'a' not found in D:\laragon\www\php_book\1_23_register_shutdown.php:31 Stack trace: #0 {main} thrown [file] => D:\laragon\www\php_book\1_23_register_shutdown.php [line] => 31 ) Stop.
注意:PHP7中新增了Throwable異常類(lèi),這個(gè)類(lèi)可以捕獲致命錯(cuò)誤,即可以使用try...catch(Throwable $e)來(lái)捕獲致命錯(cuò)誤,代碼如下:
<?php try { // 將因?yàn)橹旅e(cuò)誤而中止 $a = new a(); // 這一句并沒(méi)有執(zhí)行,也沒(méi)有輸出 echo 'end'; } catch (Throwable $e) { print_r($e); echo $e->getMessage(); }
運(yùn)行:
Error Object ( [message:protected] => Class 'a' not found [string:Error:private] => [code:protected] => 0 [file:protected] => C:\laragon\www\php_book\throwable.php [line:protected] => 5 [trace:Error:private] => Array ( ) [previous:Error:private] => [xdebug_message] => Error: Class 'a' not found in C:\laragon\www\php_book\throwable.php on line 5 Call Stack: 0.0000 349856 1. {main}() C:\laragon\www\php_book\throwable.php:0 ) Class 'a' not found
這樣的話,PHP7中使用Throwable來(lái)捕獲的話比使用register_shutdown_function這個(gè)函數(shù)來(lái)得更方便,也更推薦Throwable。
注意:Error類(lèi)也是可以捕獲到致命錯(cuò)誤,不過(guò)Error只能捕獲致命錯(cuò)誤,不能捕獲異常Exception,而Throwable是可以捕獲到錯(cuò)誤和異常的,所以更推薦。
6.巧用register_shutdown_function判斷php程序是否執(zhí)行完
還有一種應(yīng)用場(chǎng)景就是:要做一個(gè)消費(fèi)隊(duì)列,因?yàn)槟硹l有問(wèn)題的數(shù)據(jù)導(dǎo)致致命錯(cuò)誤,如果這條數(shù)據(jù)不處理掉,那么整個(gè)隊(duì)列都會(huì)導(dǎo)致癱瘓的狀態(tài),這樣可以用以下方法來(lái)解決。即:如果捕獲到有問(wèn)題的數(shù)據(jù)導(dǎo)致錯(cuò)誤,則在回調(diào)函數(shù)中將這條數(shù)據(jù)處理掉就可以了。
php范例參考與解析:
<?php register_shutdown_function('myFun'); //放到最上面,不然如果下面有致命錯(cuò)誤,就不會(huì)調(diào)用myFun了。 $execDone = false; //程序是否成功執(zhí)行完(默認(rèn)為false) /** ********************* 業(yè)務(wù)邏輯區(qū)************************* */ $tas = 3; if($tas == 3) { new daixiaorui(); } /** ********************* 業(yè)務(wù)邏輯結(jié)束************************* */ $execDone = true; //由于程序由上至下執(zhí)行,因此當(dāng)執(zhí)行到此后,則證明邏輯沒(méi)有出現(xiàn)致命的錯(cuò)誤。 function myFun() { global $execDone; if($execDone === false) { file_put_contents("E:/myMsg.txt", date("Y-m-d H:i:s")."---error: 程序執(zhí)行出錯(cuò)。\r\n", FILE_APPEND); /******** 以下可以做一些處理 ********/ } }
看完上述內(nèi)容,你們對(duì)怎么在PHP中使用register_shutdown_function函數(shù)有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。