この記事では主にphp5とphp7の例外処理の仕組み(thinkphp5の例外処理の分析)を紹介しますので、困っている方の参考になれば幸いです。
1.php の例外とエラー
他の言語では例外とエラーは異なりますが、PHP は独自のエラーが発生するとエラーをトリガーします。例外。さらに、ほとんどの場合、PHP はエラーをトリガーしてプログラムの実行を終了しますが、PHP5 では try catch にはエラーを処理する方法がありません。
php7 はエラーをキャプチャできます;
1.1 php5 エラー例外
// 1.异常处理 try{ throw new Exception("Error Processing Request", 1); }catch ( Exception $e){ echo $e->getCode().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getMessage().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getLine().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getFile().'076402276aae5dbec7f672f8f4e5cc81'; } 返回: 1 Error Processing Request 158 E:\phpwebenv\PHPTutorial\WWW\test\index.php // 2.结果php错误处理机制 function MyErrorHandler($error,$errstr,$errfile,$errline){ echo 'a4b561c25d9afb9ac8dc4d70affff419 Custom error:0d36329ec37a2cc24d42c7229b69747a'.$error.':'.$errstr.'076402276aae5dbec7f672f8f4e5cc81'; echo "Error on line $errline in ".$errfile; } set_error_handler('MyErrorHandler',E_ALL|E_STRICT); try{ // throw new Exception("Error Processing Request", 4); trigger_error('error_msg'); }catch ( Exception $e){ echo $e->getCode().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getMessage().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getLine().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getFile().'076402276aae5dbec7f672f8f4e5cc81'; } 结果: Custom error:1024:error_msg Error on line 164 in E:\phpwebenv\PHPTutorial\WWW\test\index.php //3. 处理致命错误:脚本结束后执行 function shutdown_function(){ $e = error_get_last(); echo '0141e64b460264de306a9735a1994788'; var_dump($e); } register_shutdown_function('shutdown_function'); try{ // throw new Exception("Error Processing Request", 4); // trigger_error('error_msg'); fun(); }catch ( Exception $e){ echo $e->getCode().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getMessage().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getLine().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getFile().'076402276aae5dbec7f672f8f4e5cc81'; } 结果: Fatal error: Uncaught Error: Call to undefined function fun() in E:\phpwebenv\PHPTutorial\WWW\ test\index.php:172 Stack trace: #0 {main} thrown in E:\phpwebenv\PHPTutorial\WWW\test\index.php on line 172 array(4) { ["type"]=> int(1) ["message"]=> string(131) "Uncaught Error: Call to undefined function fun() in E:\phpwebenv\PHPTutorial\WWW\test\index.php:172 Stack trace: #0 {main} thrown" ["file"]=> string(43) "E:\phpwebenv\PHPTutorial\WWW\test\index.php" ["line"]=> int(172) } 以上方法可以看出,php没有捕获到异常,只能依赖set_error_handler()和register_shutdown_function();来处理,set_error_handler只能接受 异常和非致命的错误。register_shutdown_function():主要针对die()或致命错误,即程序终结后执行;所以php5没有很好的异常处理机制。
1.2 php7 例外処理
// 处理致命错误:脚本结束后执行 function shutdown_function(){ $e = error_get_last(); echo 'e03b848252eb9375d56be284e690e873'; var_dump($e); } register_shutdown_function('shutdown_function'); // 结果php错误处理机制 function MyErrorHandler($error,$errstr,$errfile,$errline){ echo 'a4b561c25d9afb9ac8dc4d70affff419 Custom error:0d36329ec37a2cc24d42c7229b69747a'.$error.':'.$errstr.'076402276aae5dbec7f672f8f4e5cc81'; echo "Error on line $errline in ".$errfile; } set_error_handler('MyErrorHandler',E_ALL|E_STRICT); try{ // throw new Exception("Error Processing Request", 4); // trigger_error('error_msg'); fun(); }catch ( Error $e){ echo $e->getCode().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getMessage().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getLine().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getFile().'076402276aae5dbec7f672f8f4e5cc81'; } 结果: 0 Call to undefined function fun() 172 E:\phpwebenv\PHPTutorial\WWW\test\index.php NULL register_shutdown_function();没有捕获到异常
// 2. 如果不用try catch 捕获 function exception_handler( Throwable $e){ echo 'catch Error:'.$e->getCode().':'.$e->getMessage().'<br/>'; } set_exception_handler('exception_handler'); fun();
概要: Throwable はエラーと例外の基本クラスです。php7 では、例外をキャッチしたい場合は、エラーをキャッチする必要があります。
try{ fun(); }catch ( Throwable $e){ echo $e->getCode().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getMessage().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getLine().'076402276aae5dbec7f672f8f4e5cc81'; echo $e->getFile().'076402276aae5dbec7f672f8f4e5cc81'; }
3. thinkphp5 フレームワークのエラー処理:
在异常错误处理类:Error有这个处理 // 注册错误和异常处理机制 \think\Error::register(); /** * 注册异常处理 * @return void */ public static function register() { error_reporting(E_ALL); set_error_handler([__CLASS__, 'appError']); set_exception_handler([__CLASS__, 'appException']); register_shutdown_function([__CLASS__, 'appShutdown']); } 当程序出现错误时,会执行这些异常、错误的函数;
データベースに接続した後、例外は次のように処理されます。
/** * 连接数据库方法 * @access public * @param array $config 连接参数 * @param integer $linkNum 连接序号 * @param array|bool $autoConnection 是否自动连接主数据库(用于分布式) * @return PDO * @throws Exception */ public function connect(array $config = [], $linkNum = 0, $autoConnection = false) { if (!isset($this->links[$linkNum])) { if (!$config) { $config = $this->config; } else { $config = array_merge($this->config, $config); } // 连接参数 if (isset($config['params']) && is_array($config['params'])) { $params = $config['params'] + $this->params; } else { $params = $this->params; } // 记录当前字段属性大小写设置 $this->attrCase = $params[PDO::ATTR_CASE]; // 数据返回类型 if (isset($config['result_type'])) { $this->fetchType = $config['result_type']; } try { if (empty($config['dsn'])) { $config['dsn'] = $this->parseDsn($config); } if ($config['debug']) { $startTime = microtime(true); } $this->links[$linkNum] = new PDO($config['dsn'], $config['username'], $config['password'], $params); if ($config['debug']) { // 记录数据库连接信息 Log::record('[ DB ] CONNECT:[ UseTime:' . number_format(microtime(true) - $startTime, 6) . 's ] ' . $config['dsn'], 'sql'); } } catch (\PDOException $e) { if ($autoConnection) { Log::record($e->getMessage(), 'error'); return $this->connect($autoConnection, $linkNum); } else { throw $e; } } } return $this->links[$linkNum]; } 当数据库链接失败后,可以重新链接或者直接抛出异常; /** * 析构方法 * @access public */ public function __destruct() { // 释放查询 if ($this->PDOStatement) { $this->free(); } // 关闭连接 $this->close(); } 当执行sql失败后,调用析构方法,关闭数据库链接;
4. PHP でエラーが発生すると、リソースが解放されます
#php は説明用のスクリプトであり、PHP の各ページは独立した実行プログラムであり、どのような方法で実行しても (die()、exit()、致命的エラー終了プログラムも含む)、結果が返されます。サーバーに送信すると閉じられます。プログラムが閉じられると、当然リソースは解放されます; unset(); 複数の変数名またはオブジェクト名がストレージ アドレスを指している場合、unset() 関数の機能は、そのアドレスを破棄することだけです。変数名と格納アドレスのポインタ 以上です、変数名またはオブジェクト名が 1 つだけの場合、unset は指定された格納アドレスの内容を破棄します; 破棄方法: インスタンス化されたオブジェクトに他の変数がない場合またはそれを指すオブジェクト名がある場合、このメソッドが実行されます。または、スクリプトの終了後にオブジェクト リソースが解放されたときにこのメソッドが実行されます。関連する推奨事項: PHP7 と PHP5 のセキュリティの違い (例) )>>PHP7 の抽象構文ツリー (AST) によってもたらされる変更点 >>PHP7言語の実行原理(PHP7ソースコード解析)>>《PHP 7.4は2019年12月リリース予定>>
以上がphp5とphp7の例外処理機構(thinkphp5の例外処理の分析)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。