GVKun编程网logo

PHP各种异常和错误的拦截方法及发生致命错误时进行报警(php 错误和异常处理)

24

本文的目的是介绍PHP各种异常和错误的拦截方法及发生致命错误时进行报警的详细情况,特别关注php错误和异常处理的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解PHP各

本文的目的是介绍PHP各种异常和错误的拦截方法及发生致命错误时进行报警的详细情况,特别关注php 错误和异常处理的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解PHP各种异常和错误的拦截方法及发生致命错误时进行报警的机会,同时也不会遗漏关于Delphi--异常和错误处理、php – Codeigniter扩展自定义模型会产生致命错误、php – 在money_format函数中发生致命错误、PHP 单元测试:如何处理异常和错误?的知识。

本文目录一览:

PHP各种异常和错误的拦截方法及发生致命错误时进行报警(php 错误和异常处理)

PHP各种异常和错误的拦截方法及发生致命错误时进行报警(php 错误和异常处理)

在日常开发中,大多数人的做法是在开发环境时开启调试模式,在产品环境关闭调试模式。在开发的时候可以查看各种错误、异常,但是在线上就把错误显示的关闭。

上面的情形看似很科学,有人解释为这样很安全,别人看不到错误,以免泄露重要信息...

但是你有没有遇到这种情况,线下好好的,一上线却运行不起来也找不到原因...

一个脚本,跑了好长一段时间,一直没有问题,有一天突然中断了,然后了也没有任何记录都不造啥原因...

线上一个付款,别人明明付了款,但是我们却没有记录到,自己亲自去实验,却是好的...

种种以上,都是因为大家关闭了错误信息,并且未将错误、异常记录到日志,导致那些随机发生的错误很难追踪。这样矛盾就来了,即不要显示错误,又要追踪错误,这如何实现了?

以上问题都可以通过PHP的错误、异常机制及其内建函数''set_exception_handler'',''set_error_handler'',''register_shutdown_function'' 来实现

''set_exception_handler'' 函数 用于拦截各种未捕获的异常,然后将这些交给用户自定义的方式进行处理

''set_error_handler'' 函数可以拦截各种错误,然后交给用户自定义的方式进行处理

''register_shutdown_function'' 函数是在PHP脚本结束时调用的函数,配合''error_get_last''可以获取最后的致命性错误

这个思路大体就是把错误、异常、致命性错误拦截下来,交给我们自定义的方法进行处理,我们辨别这些错误、异常是否致命,如果是则记录的数据库或者文件系统,然后使用脚本不停的扫描这些日志,发现严重错误立即发送邮件或发送短信进行报警

首先我们定义错误拦截类,该类用于将错误、异常拦截下来,用我们自己定义的处理方式进行处理,该类放在文件名为''errorHandler.class.php''中,代码如下

/**
 * 文件名称:baseErrorHandler.class.php
 * 摘 要:错误拦截器父类
 */
require ''errorHandlerException.class.php'';//异常类
class errorHandler
{
 public $argvs = array();
 public  $memoryReserveSize = 262144;//备用内存大小
 private $_memoryReserve;//备用内存
 /**
  * 方  法:注册自定义错误、异常拦截器
  * 参  数:void
  * 返  回:void
  */
 public function register()
 {
  ini_set(''display_errors'', 0);
  set_exception_handler(array($this, ''handleException''));//截获未捕获的异常
  set_error_handler(array($this, ''handleError''));//截获各种错误 此处切不可掉换位置
  //留下备用内存 供后面拦截致命错误使用
  $this->memoryReserveSize > 0 && $this->_memoryReserve = str_repeat(''x'', $this->memoryReserveSize);
  register_shutdown_function(array($this, ''handleFatalError''));//截获致命性错误
 }
 /**
  * 方  法:取消自定义错误、异常拦截器
  * 参  数:void
  * 返  回:void
  */
 public function unregister()
 {
  restore_error_handler();
  restore_exception_handler();
 }
 /**
  * 方  法:处理截获的未捕获的异常
  * 参  数:Exception $exception
  * 返  回:void
  */
 public function handleException($exception)
 {
  $this->unregister();
  try
  {
   $this->logException($exception);
   exit(1);
  }
  catch(Exception $e)
  {
   exit(1);
  }
 }
 /**
  * 方  法:处理截获的错误
  * 参  数:int  $code 错误代码
  * 参  数:string $message 错误信息
  * 参  数:string $file 错误文件
  * 参  数:int  $line 错误的行数
  * 返  回:boolean
  */
 public function handleError($code, $message, $file, $line)
 {
  //该处思想是将错误变成异常抛出 统一交给异常处理函数进行处理
  if((error_reporting() & $code) && !in_array($code, array(E_NOTICE, E_WARNING, E_USER_NOTICE, E_USER_WARNING, E_DEPRECATED)))
  {//此处只记录严重的错误 对于各种WARNING NOTICE不作处理
   $exception = new errorHandlerException($message, $code, $code, $file, $line);
   $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
   array_shift($trace);//trace的第一个元素为当前对象 移除
   foreach($trace as $frame) 
   {
    if($frame[''function''] == ''__toString'') 
    {//如果错误出现在 __toString 方法中 不抛出任何异常
     $this->handleException($exception);
     exit(1);
    }
   }
   throw $exception;
  }
  return false;
 }
 /**
  * 方  法:截获致命性错误
  * 参  数:void
  * 返  回:void
  */
 public function handleFatalError()
 {
  unset($this->_memoryReserve);//释放内存供下面处理程序使用
  $error = error_get_last();//最后一条错误信息
  if(errorHandlerException::isFatalError($error))
  {//如果是致命错误进行处理
   $exception = new errorHandlerException($error[''message''], $error[''type''], $error[''type''], $error[''file''], $error[''line'']);
   $this->logException($exception);
   exit(1);
  }
 }
 /**
  * 方  法:获取服务器IP
  * 参  数:void
  * 返  回:string
  */
 final public function getServerIp()
 {
  $serverIp = '''';
  if(isset($_SERVER[''SERVER_ADDR'']))
  {
   $serverIp = $_SERVER[''SERVER_ADDR''];
  }
  elseif(isset($_SERVER[''LOCAL_ADDR'']))
  {
   $serverIp = $_SERVER[''LOCAL_ADDR''];
  }
  elseif(isset($_SERVER[''HOSTNAME'']))
  {
   $serverIp = gethostbyname($_SERVER[''HOSTNAME'']);
  }
  else
  {
   $serverIp = getenv(''SERVER_ADDR'');
  }  
  return $serverIp; 
 }
 /**
  * 方  法:获取当前URI信息
  * 参  数:void
  * 返  回:string $url
  */
 public function getCurrentUri()
 {
  $uri = '''';
  if($_SERVER ["REMOTE_ADDR"])
  {//浏览器浏览模式
   $uri = ''http://'' . $_SERVER[''SERVER_NAME''] . $_SERVER[''REQUEST_URI''];
  }
  else
  {//命令行模式
   $params = $this->argvs;
   $uri = $params[0];
   array_shift($params);
   for($i = 0, $len = count($params); $i < $len; $i++)
   {
    $uri .= '' '' . $params[$i];
   }
  }
  return $uri;
 }
 /**
  * 方  法:记录异常信息
  * 参  数:errorHandlerException $e 错误异常
  * 返  回:boolean 是否保存成功
  */
 final public function logException($e)
 {
  $error = array(
      ''add_time''  =>  time(),
      ''title''  =>  errorHandlerException::getName($e->getCode()),//这里获取用户友好型名称
      ''message''  =>  array(),
      ''server_ip'' =>  $this->getServerIp(),
      ''code''   =>  errorHandlerException::getLocalCode($e->getCode()),//这里为各种错误定义一个编号以便查找
      ''file''   => $e->getFile(),
      ''line''   =>  $e->getLine(),
      ''url''  => $this->getCurrentUri(),
     );
  do
  {
   //$e->getFile() . '':'' . $e->getLine() . '' '' . $e->getMessage() . ''('' . $e->getCode() . '')''
   $message = (string)$e;
   $error[''message''][] = $message;
  } while($e = $e->getPrevious());
  $error[''message''] = implode("\r\n", $error[''message'']);
  $this->logError($error);
 }
 /**
  * 方  法:记录异常信息
  * 参  数:array $error = array(
  *         ''time'' => int, 
  *         ''title'' => ''string'', 
  *         ''message'' => ''string'', 
  *         ''code'' => int,
  *         ''server_ip'' => ''string''
  *          ''file''  => ''string'',
  *         ''line'' => int,
  *         ''url'' => ''string'',
  *        );
  * 返  回:boolean 是否保存成功
  */
 public function logError($error)
 {
  /*这里去实现如何将错误信息记录到日志*/
 }
}

上述代码中,有个''errorHandlerException''类,该类放在文件''errorHandlerException.class.php''中,该类用于将错误转换为异常,以便记录错误发生的文件、行号、错误代码、错误信息等信息,同时其方法''isFatalError''用于辨别该错误是否是致命性错误。这里我们为了方便管理,将错误进行编号并命名。该类的代码如下

/**
 * 文件名称:errorHandlerException.class.php
 * 摘 要:自定义错误异常类 该类继承至PHP内置的错误异常类
 */
class errorHandlerException extends ErrorException
{
 public static $localCode = array(
          E_COMPILE_ERROR => 4001,
          E_COMPILE_WARNING => 4002,
          E_CORE_ERROR => 4003,
          E_CORE_WARNING => 4004,
          E_DEPRECATED => 4005,
          E_ERROR => 4006,
          E_NOTICE => 4007,
          E_PARSE => 4008,
          E_RECOVERABLE_ERROR => 4009,
          E_STRICT => 4010,
          E_USER_DEPRECATED => 4011,
          E_USER_ERROR => 4012,
          E_USER_NOTICE => 4013,
          E_USER_WARNING => 4014,
          E_WARNING => 4015,
          4016 => 4016,
         );
 public static $localName = array(
          E_COMPILE_ERROR => ''PHP Compile Error'',
          E_COMPILE_WARNING => ''PHP Compile Warning'',
          E_CORE_ERROR => ''PHP Core Error'',
          E_CORE_WARNING => ''PHP Core Warning'',
          E_DEPRECATED => ''PHP Deprecated Warning'',
          E_ERROR => ''PHP Fatal Error'',
          E_NOTICE => ''PHP Notice'',
          E_PARSE => ''PHP Parse Error'',
          E_RECOVERABLE_ERROR => ''PHP Recoverable Error'',
          E_STRICT => ''PHP Strict Warning'',
          E_USER_DEPRECATED => ''PHP User Deprecated Warning'',
          E_USER_ERROR => ''PHP User Error'',
          E_USER_NOTICE => ''PHP User Notice'',
          E_USER_WARNING => ''PHP User Warning'',
          E_WARNING => ''PHP Warning'',
          4016 => ''Customer`s Error'',
         );
 /**
  * 方  法:构造函数
  * 摘  要:相关知识请查看 http://php.net/manual/en/errorexception.construct.php
  * 
  * 参  数:string  $message  异常信息(可选)
  *    int   $code   异常代码(可选)
  *    int   $severity
  *    string  $filename  异常文件(可选)
  *    int   $line   异常的行数(可选)
  *   Exception $previous 上一个异常(可选)
  *
  * 返  回:void
  */
 public function __construct($message = '''', $code = 0, $severity = 1, $filename = __FILE__, $line = __LINE__, Exception $previous = null)
 {
  parent::__construct($message, $code, $severity, $filename, $line, $previous);
 }
 /**
  * 方  法:是否是致命性错误
  * 参  数:array $error
  * 返  回:boolean
  */
 public static function isFatalError($error)
 {
  $fatalErrors = array(
        E_ERROR, 
        E_PARSE, 
        E_CORE_ERROR,
        E_CORE_WARNING, 
        E_COMPILE_ERROR, 
        E_COMPILE_WARNING
       );
  return isset($error[''type'']) && in_array($error[''type''], $fatalErrors);
 }
 /**
  * 方  法:根据原始的错误代码得到本地的错误代码
  * 参  数:int $code
  * 返  回:int $localCode
  */
 public static function getLocalCode($code)
 {
  return isset(self::$localCode[$code]) ? self::$localCode[$code] : self::$localCode[4016];
 }
 /**
  * 方  法:根据原始的错误代码获取用户友好型名称
  * 参  数:int 
  * 返  回:string $name
  */
 public static function getName($code)
 {
  return isset(self::$localName[$code]) ? self::$localName[$code] : self::$localName[4016];
 }

在错误拦截类中,需要用户自己定义实现错误记录的方法(''logException''),这个地方需要注意,有些错误可能在一段时间内不断发生,因此只需记录一次即可,你可以使用错误代码、文件、行号、错误详情 生成一个MD5值用于记录该错误是否已经被记录,如果在规定时间内(一个小时)已经被记录过则不需要再进行记录

然后我们定义一个文件,用于实例化以上类,捕获各种错误、异常,该文件命名为''registerErrorHandler.php'', 内如如下

/*
* 使用方法介绍:
* 在入口处引入该文件即可,然后可以在该文件中定义调试模式常量''DEBUG_ERROR''
*
* <?php
* 
* require ''registerErrorHandler.php'';
* 
* ?>
*/
/**
* 调试错误模式:
* 0    =>   非调试模式,不显示异常、错误信息但记录异常、错误信息
* 1    =>   调试模式,显示异常、错误信息但不记录异常、错误信息
*/
define(''DEBUG_ERROR'', 0);
require ''errorHandler.class.php'';
class registerErrorHandler
{
 /**
  * 方  法:注册异常、错误拦截
  * 参  数:void
  * 返  回:void
  */
 public static function register()
 {
  global $argv;
  if(DEBUG_ERROR)
  {//如果开启调试模式
   ini_set(''display_errors'', 1);
   return;
  }
  //如果不开启调试模式
  ini_set(''error_reporting'', -1);
  ini_set(''display_errors'', 0);
  $handler = new errorHandler();
  $handler->argvs = $argv;//此处主要兼容命令行模式下获取参数
  $handler->register();
 } 
}
registerErrorHandler::register(); 

剩下的就是需要你在你的入口文件引入该文件,定义调试模式,然后实现你自己记录错误的方法即可

需要注意的是,有些错误在你进行注册之前已经发生并且导致脚本中断是无法记录下来的,因为此时''registerErrorHandler::register()'' 尚未执行已经中断了

还有就是''set_error_handler''这个函数不能捕获下面类型的错误 E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、E_COMPILE_ERROR、 E_COMPILE_WARNING, 这个可以在官方文档中看到,但是本处无妨,因为以上错误是解析、编译错误,这些都没有通过,你是不可能发布上线的

您可能感兴趣的文章:
  • 基于PHP7错误处理与异常处理方法(详解)
  • PHP中常见的错误与异常处理总结大全
  • php中的异常和错误浅析
  • 浅谈PHP中的错误处理和异常处理
  • PHP错误和异常处理功能模块示例
  • PHP中错误与异常的日志记录用法分析
  • PHP异常Parse error: syntax error, unexpected T_VAR错误解决方法
  • 一个显示效果非常不错的PHP错误、异常处理类
  • PHP 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
  • php错误、异常处理机制(补充)
  • PHP中的错误处理、异常处理机制分析
  • PHP如何抛出异常处理错误
  • 再谈PHP错误与异常处理

Delphi--异常和错误处理

Delphi--异常和错误处理

总结

以上是小编为你收集整理的Delphi--异常和错误处理全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

php – Codeigniter扩展自定义模型会产生致命错误

php – Codeigniter扩展自定义模型会产生致命错误

我已经看到了几个不同的帖子,但它们似乎都不适合我.

我有一个扩展CI_Model的类:

class Users_Model extends CI_Model {

public function __construct(){
    parent::__construct();
}

然后:

class Students_Model extends Users_Model {

private $_students;

public function __construct(){
      parent::__construct();

      $this->_students = $this->get_students();
}

但是,然后我收到此错误消息:

PHP Fatal error:  Class 'Users_Model' not found in /Users/rosswilson/Localhost/thedrumrooms/dreamweaver/ci/application/models/students_model.PHP

我已经使用require_once将文件包含在扩展类中并且它可以工作.
这是最好的做法/正确的方法吗?

谢谢.

解决方法:

CI中的标准做法是在名为MY_Model.PHP的应用程序/核心内创建基本模型,MY_取决于您的配置中定义的内容.

然后在你的MY_Model.PHP中你可以在你的模型中扩展该文件中定义的许多类,基本上CodeIgniter的加载模型在这个路径和文件中查找已定义的类.

但是如果你想使用require_once,你必须使用index.PHP中定义的APPPATH(应用程序路径).但是,您的自定义模型仍然需要扩展CI_Model,因为它使用CI模型的核心类,否则您的模型将无法工作.

ex require_once APPPATH.’/ models / test.PHP’;

增加说明:

谢谢@dean或者指出这一点.在MY_Model.PHP文件中,必须有一个扩展CI_Model的MY_Model类.

php – 在money_format函数中发生致命错误

php – 在money_format函数中发生致命错误

为什么会出现此错误?

码:

setlocale(LC_MONETARY,"en_US");
$pricetotal = money_format("%10.2n",$pricetotal);

服务器详情.

Apache Version : 2.2.21  
PHP Version : 5.3.8

我收到以下错误

Fatal error: Call to undefined function money_format()
从 manual:

The function money_format() is only defined if the system has strfmon
capabilities. For example,Windows does not,so money_format() is
undefined in Windows.

money_format()基本上是作为手动状态的C库函数strfmon()的包装.

如果你查看评论,那就是an implementation by Rafael M. Salvioni.值得一试.您可以使用function_exists()检查是否已经定义.

this StackOverflow question的答案给出了更多的(甚至更好的)替代方案(thx danielson317).

PHP 单元测试:如何处理异常和错误?

PHP 单元测试:如何处理异常和错误?

处理单元测试中的异常和错误至关重要:使用 try...catch 块捕获异常或错误phpunit 断言方法:assertthrows:验证特定异常的发生assertnoexception:验证无异常发生通过这些机制,可以全面测试异常和错误,确保代码健壮性和可信度。

PHP 单元测试:如何处理异常和错误?

PHP 单元测试:如何处理异常和错误

在单元测试中处理异常和错误对于确保代码的可靠性至关重要。PHP 提供了多种机制,可以用来检测和断言异常或错误。

使用 try...catch 块

立即学习“PHP免费学习笔记(深入)”;

最直接的方法是使用 try...catch 块来捕获异常或错误:

try {
    // 代码可能会引发异常或错误
} catch (Exception $e) {
    // 处理异常
} catch (Throwable $t) {
    // 处理错误和其他可抛出对象
}
登录后复制

使用 PHPUnit\Framework\TestCase 的断言方法

PHPUnit 提供了一组断言方法,可以用来验证异常和错误的发生:

1. assertThrows

assertThrows 断言在指定代码块中会引发特定异常:

$this->assertThrows(ArithmeticError::class, function () {
    1 / 0;
});
登录后复制

2. assertNoException

assertNoException 断言在指定代码块中不会引发任何异常:

$this->assertNoException(function () {
    // 不会引发异常的代码
});
登录后复制

实战案例

以下示例展示了如何使用 PHPUnit 断言方法来测试异常处理:

class MyCalculatorTest extends TestCase
{
    public function testDivideByZero()
    {
        $this->assertThrows(ArithmeticError::class, function () {
            $calculator = new MyCalculator();
            $calculator->divide(1, 0);
        });
    }

    public function testValidDivision()
    {
        $this->assertNoException(function () {
            $calculator = new MyCalculator();
            $calculator->divide(10, 2);
        });
    }
}
登录后复制

通过使用这些机制,你可以对异常和错误进行全面测试,从而提高代码的健壮性和可信度。

以上就是PHP 单元测试:如何处理异常和错误?的详细内容,更多请关注php中文网其它相关文章!

我们今天的关于PHP各种异常和错误的拦截方法及发生致命错误时进行报警php 错误和异常处理的分享就到这里,谢谢您的阅读,如果想了解更多关于Delphi--异常和错误处理、php – Codeigniter扩展自定义模型会产生致命错误、php – 在money_format函数中发生致命错误、PHP 单元测试:如何处理异常和错误?的相关信息,可以在本站进行搜索。

本文标签: