佳木斯湛栽影视文化发展公司

主頁 > 知識庫 > PHP中register_shutdown_function函數(shù)的基礎(chǔ)介紹與用法詳解

PHP中register_shutdown_function函數(shù)的基礎(chǔ)介紹與用法詳解

熱門標(biāo)簽:服務(wù)器配置 Mysql連接數(shù)設(shè)置 阿里云 科大訊飛語音識別系統(tǒng) 電子圍欄 團(tuán)購網(wǎng)站 Linux服務(wù)器 銀行業(yè)務(wù)

前言

最近在看《PHP核心技術(shù)與最佳實(shí)踐》,里面有使用到一個函數(shù),register_shutdown_function,由于之前沒有用過該函數(shù),就去查了一下資料,就覺得是個很實(shí)用的函數(shù),所以這里寫一下這個函數(shù)的用法。下面話不多說了,來一起看看詳細(xì)的介紹吧。

1. 函數(shù)說明

定義:該函數(shù)是來注冊一個會在PHP中止時執(zhí)行的函數(shù)

參數(shù)說明:

void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] ) 

注冊一個 callback ,它會在腳本執(zhí)行完成或者 exit() 后被調(diào)用。

callback:待注冊的中止回調(diào)

parameter:可以通過傳入額外的參數(shù)來將參數(shù)傳給中止函數(shù)

2. PHP中止的情況

PHP中止的情況有三種:

  • 執(zhí)行完成
  • exit/die導(dǎo)致的中止
  • 發(fā)生致命錯誤中止

a. 第一種情況,執(zhí)行完成

?php 
function test() 
{ 
 echo '這個是中止方法test的輸出'; 
} 
 
register_shutdown_function('test'); 
 
echo 'before' . PHP_EOL; 

運(yùn)行:

before 
這個是中止方法test的輸出 

注意:輸出的順序,等執(zhí)行完成了之后才會去執(zhí)行register_shutdown_function的中止方法test

b. 第二種情況,exit/die導(dǎo)致的中止

?php 
function test() 
{ 
 echo '這個是中止方法test的輸出'; 
} 
 
register_shutdown_function('test'); 
 
echo 'before' . PHP_EOL; 
exit(); 
echo 'after' . PHP_EOL; 

運(yùn)行:

before 
這個是中止方法test的輸出 

后面的after并沒有輸出,即exit或者是die方法導(dǎo)致提前中止。

c. 第三種情況,發(fā)送致命錯誤中止

?php 
function test() 
{ 
 echo '這個是中止方法test的輸出'; 
} 
 
register_shutdown_function('test'); 
 
echo 'before' . PHP_EOL; 
 
// 這里會發(fā)生致命錯誤 
$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 
 
這個是中止方法test的輸出 

后面的after也是沒有輸出,致命錯誤導(dǎo)致提前中止了。

3. 參數(shù)

第一個參數(shù)支持以數(shù)組的形式來調(diào)用類中的方法,第二個以及后面的參數(shù)都是可以當(dāng)做額外的參數(shù)傳給中止方法。

?php 
 
class Shutdown 
{ 
 public function stop() 
 { 
  echo "這個是stop方法的輸出"; 
 } 
} 
 
// 當(dāng)PHP終止的時候(執(zhí)行完成或者是遇到致命錯誤中止的時候)會調(diào)用new Shutdown的stop方法 
register_shutdown_function([new Shutdown(), 'stop']); 
 
// 將因?yàn)橹旅e誤而中止 
$a = new a(); 
 
// 這一句并沒有執(zhí)行,也沒有輸出 
echo '必須終止'; 

也可以在類中執(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. 同時調(diào)用多個

可以多次調(diào)用 register_shutdown_function,這些被注冊的回調(diào)會按照他們注冊時的順序被依次調(diào)用。

不過注意的是,如果在第一個注冊的中止方法里面調(diào)用exit方法或者是die方法的話,那么其他注冊的中止回調(diào)也不會被調(diào)用。
代碼:

?php 
/** 
 * 可以多次調(diào)用 register_shutdown_function,這些被注冊的回調(diào)會按照他們注冊時的順序被依次調(diào)用。 
 * 注意:如果你在f方法(第一個注冊的方法)里面調(diào)用exit方法或者是die方法的話,那么其他注冊的中止回調(diào)也不會被調(diào)用 
 */ 
 
/** 
 * @param $str 
 */ 
function f($str) { 
 echo $str . PHP_EOL; 
 
 // 如果下面調(diào)用exit方法或者是die方法的話,其他注冊的中止回調(diào)不會被調(diào)用 
 // exit(); 
} 
 
// 注冊第一個中止回調(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不會輸出 
 */ 

5. 用處

該函數(shù)的作用:

析構(gòu)函數(shù):在PHP4的時候,由于類不支持析構(gòu)函數(shù),所以這個函數(shù)經(jīng)常用來模擬實(shí)現(xiàn)析構(gòu)函數(shù)

致命錯誤的處理:使用該函數(shù)可以用來捕獲致命錯誤并且在發(fā)生致命錯誤后恢復(fù)流程處理

代碼如下:

?php 
/** 
 * register_shutdown_function,注冊一個會在php中止時執(zhí)行的函數(shù),中止的情況包括發(fā)生致命錯誤、die之后、exit之后、執(zhí)行完成之后都會調(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ā)生錯誤(所有的錯誤,包括致命和非致命)的話,獲取最后發(fā)生的錯誤 
  if (error_get_last()) { 
   print_r(error_get_last()); 
  } 
 
  // ToDo:發(fā)生致命錯誤后恢復(fù)流程處理 
 
  // 中止后面的所有處理 
  die('Stop.'); 
 } 
} 
 
// 當(dāng)PHP終止的時候(執(zhí)行完成或者是遇到致命錯誤中止的時候)會調(diào)用new Shutdown的stop方法 
register_shutdown_function([new Shutdown(), 'stop']); 
 
// 將因?yàn)橹旅e誤而中止 
$a = new a(); 
 
// 這一句并沒有執(zhí)行,也沒有輸出 
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異常類,這個類可以捕獲致命錯誤,即可以使用try...catch(Throwable $e)來捕獲致命錯誤,代碼如下:

?php 
 
try { 
 // 將因?yàn)橹旅e誤而中止 
 $a = new a(); 
 
 // 這一句并沒有執(zhí)行,也沒有輸出 
 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來捕獲的話比使用register_shutdown_function這個函數(shù)來得更方便,也更推薦Throwable。

注意:Error類也是可以捕獲到致命錯誤,不過Error只能捕獲致命錯誤,不能捕獲異常Exception,而Throwable是可以捕獲到錯誤和異常的,所以更推薦。

6.巧用register_shutdown_function判斷php程序是否執(zhí)行完

還有一種應(yīng)用場景就是:要做一個消費(fèi)隊(duì)列,因?yàn)槟硹l有問題的數(shù)據(jù)導(dǎo)致致命錯誤,如果這條數(shù)據(jù)不處理掉,那么整個隊(duì)列都會導(dǎo)致癱瘓的狀態(tài),這樣可以用以下方法來解決。即:如果捕獲到有問題的數(shù)據(jù)導(dǎo)致錯誤,則在回調(diào)函數(shù)中將這條數(shù)據(jù)處理掉就可以了。

php范例參考與解析:

?php

register_shutdown_function('myFun'); //放到最上面,不然如果下面有致命錯誤,就不會調(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í)行到此后,則證明邏輯沒有出現(xiàn)致命的錯誤。

function myFun()
{
global $execDone;
if($execDone === false)
{
file_put_contents("E:/myMsg.txt", date("Y-m-d H:i:s")."---error: 程序執(zhí)行出錯。\r\n", FILE_APPEND);
/******** 以下可以做一些處理 ********/
}
}

總結(jié)

register_shutdown_function這個函數(shù)主要是用在處理致命錯誤的后續(xù)處理上(PHP7更推薦使用Throwable來處理致命錯誤),不過缺點(diǎn)也很明顯,只能處理致命錯誤Fatal error,其他的錯誤包括最高錯誤Parse error也是沒辦法處理的。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • PHP register_shutdown_function函數(shù)的深入解析
  • php ignore_user_abort與register_shutdown_function 使用方法
  • PHP register_shutdown_function()函數(shù)的使用示例
  • php中__destruct與register_shutdown_function執(zhí)行的先后順序問題
  • PHP中使用register_shutdown_function函數(shù)截獲fatal error示例
  • PHP錯誤處理函數(shù)register_shutdown_function使用示例
  • php register_shutdown_function函數(shù)詳解

標(biāo)簽:蚌埠 衡水 江蘇 萍鄉(xiāng) 棗莊 廣元 衢州 大理

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP中register_shutdown_function函數(shù)的基礎(chǔ)介紹與用法詳解》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    南皮县| 淳安县| 罗定市| 石柱| 石阡县| 乌苏市| 大田县| 石林| 连平县| 绍兴县| 江津市| 福泉市| 平乡县| 陈巴尔虎旗| 元江| 泰兴市| 阜宁县| 临海市| 望城县| 三门峡市| 桂平市| 桓台县| 桃源县| 常熟市| 邹城市| 休宁县| 顺平县| 新化县| 马鞍山市| 张家川| 石首市| 凌源市| 吉木乃县| 保康县| 铁岭市| 黄石市| 连山| 彰化县| 丰县| 门头沟区| 佳木斯市|