PHP 最佳实践之异常和错误

异常

1).异常是Exception类的对象,在遇到无法修复的状况时抛出,例如远程API没有响应或者数据库查询失败再或者是无法满足程序运行的前置条件。出现问题的时候异常用于主动出击,委托职责;异常还可以用于防守,预测潜在的问题来减轻影响。
2).Exception对象和其他的PHP对象一样,使用new关键字实例化。

<?php
$exception = new Exception('userId cannot be null', 100);

第一个参数是消息,第二个参数是数字代码。数字代码是可选的,用于为指定的异常提供上下文。我们可以使用公开的实例方法getCodegetMessage来获得异常对象的两个属性。
3).假如遇到了异常情况,或者在当前的条件下无法操作,我们需要抛出异常。

<?php
throw new Exception('Something went wrong.Time for lunch!');

4).我们必须抛出Exception类或者他的子类,PHP内置的异常类和其子类如下:

  • Exception
  • ErrorException
    PHP标准库提供了下述额外的Exception子类,扩展了PHP内置的异常类。
  • LogicException
    • BadFunctionCallException
    • BadMethodCallException
    • DomainException
    • InvalidArgumentException
    • LengthException
    • OutOfBoundsException
  • RuntimeException
    • OutOfBoundsException
    • OverflowException
    • RangeException
    • UnderflowException
    • UnexpectedValueException

5).捕获异常。预测和捕获并处理异常是我们自己的责任,因为未捕获的异常可能会导致PHP应用终止运行,显示错误信息。拦截并处理潜在异常的方式是,把可能抛出异常的代码放在在try/catch块中。

try {
    $pdo = new PDO('mysql://host=wrong_host;dbname=wrong_name');
} catch (PDOException $e) {
    $code = $e->getCode();
    $message = $e->getMessage();
    echo 'Something went wrong.Check back soon, please';
    exit;
}

还可以连续抛出多个异常

try {
  throw new Exception('Not a PDO exception');
  $pdo = new PDO('mysql://host=wrong_host;dbname=wrong_name');
} catch (PDOException $e) {
    echo 'Caught PDO exception';
} catch (Exception $e) {
    //处理其他异常
    echo 'Caught generic exception';
} finally {
    //这里的代码始终都会执行
    echo 'Always do this';
}

捕获某种异常的时候只会允许其中一个catch块,如果PHP没有找到适用的catch块,异常会向上冒泡,直到PHP脚本由于致命的错误而终止。
6).异常处理程序。我们可以使用一个全局的异常处理程序,来捕获所有未被捕获的异常。异常捕获程序都必须接受一个了类型为Exception的参数,异常捕获程序使用set_exception_handler()函数注册。

<?php
set_exception_handler(function (Exception $e) {
    //处理并记录异常
});

//你的代码
...

//还原成之前的异常处理程序
restore_exception_handler();
错误

1).我们可以使用error_reporting()函数或者在php.ini文件中使用errorreporting指令告诉PHP报告或者忽略那些错误。这两种都是使用E*常量来确定。
2)错误报告方式四原则:

  • 一定要让PHP报告错误
  • 在开发环境中要显示错误
  • 再生产环境中不能显示错误
  • 在开发和生产环境中都要记录错误

3)一种php.ini配置的例子:
开发环境:

;显示错误
display_startup_errors = On
display_errors = On
;报告所有错误
error_reporting = -1
; 记录错误
log_errors = On

生产环境:

;不显示错误
display_startup_errors = Off
display_errors = Off
;除了注意事项外,报告所有错误
error_reporting = E_ALL & ~E_NOTICE
; 记录错误
log_errors = On

4).注册全局的错误处理程序:set_error_handler()函数。

<?php
set_error_handler(function($errno, $errstr, $errfile, $errline) {
    //处理错误
    //$errno表示错误等级对应E_*常量
    //$errcontext是一个省略的参数,高级调试才用到
});

5.一个简单的全局错误处理程序的例子:

set_error_handler(function($errno, $errstr, $errfile, $errline) {
   if (!(error_reporting() & $errno)) {
    //error_reporting指令没有设置这个错误,所以忽略
    return;  
  }
  throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});

//其他代码

//还原成之前的错误处理程序
restore_error_handler();
相关处理组件
  • 开发环境: filp/whoops
  • 生产环境: monolog/monolog

专题系列

PHP专题系列目录地址:https://github.com/xx19941215/webBlog
PHP专题系列预计写二十篇左右,主要总结我们日常PHP开发中容易忽略的基础知识和现代PHP开发中关于规范、部署、优化的一些实战性建议,同时还有对Javascript语言特点的深入研究。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 6

学习了,已订阅专栏,真棒!

7年前 评论

laravel 5.4 项目中, 用到的exception

1 BankAccountException
1 BroadcastException
1 ClassMirrorException
1 ClassNotFoundException
1 CloneException
1 ConflictingHeadersException
1 ContextErrorException
1 ContractFileNotFoundException
1 CoveredCodeNotExecutedException
1 DOMException
1 DeprecatedException
1 EntityNotFoundException
1 FileExistsException
1 FilesystemNotFoundException
1 HandleException
1 HttpResponseException
1 IllogicException
1 InterfaceNotFoundException
1 InvalidCallbackException
1 InvalidCountException
1 InvalidFileException
1 InvalidPathException
1 InvalidPayloadException
1 InvalidUuidStringException
1 MaintenanceModeException
1 MassAssignmentException
1 MethodNotExtendableException
1 MissingCoversAnnotationException
1 MissingMandatoryParametersException
1 NewException
1 ObjectProphecyException
1 PHPUnit_Framework_CodeCoverageException
1 ParseErrorException
1 PluginNotFoundException
1 PostTooLargeException
1 QueryException
1 RangeException
1 RootViolationException
1 Swift_DependencyException
1 ThrowException
1 ThrowUpException
1 TokenMismatchException
1 UnauthorizedException
1 UnexpectedCallsCountException
1 UnexpectedCallsException
1 UnintentionallyCoveredCodeException
1 andThrowException
2 AuthorizationException
2 BadFunctionCallException
2 BindingResolutionException
2 ClassCreatorException
2 DoubleException
2 DumpException
2 EncryptException
2 FileLoaderLoadException
2 InternalErrorException
2 InvalidDateException
2 InvalidParameterException
2 InvalidStyleException
2 LengthException
2 MethodNotFoundException
2 NoCallsException
2 OverflowException
2 PHPUnit_Framework_MockObject_BadMethodCallException
2 ReturnByReferenceException
2 RouteNotFoundException
2 SkippingException
2 SuspiciousOperationException
3 AccessDeniedHttpException
3 AuthenticationException
3 DecryptException
3 InvalidOptionException
3 MethodNotAllowedHttpException
3 PHPUnit_Framework_InvalidCoversTargetException
3 ProcessFailedException
4 AccessDeniedException
4 BreakException
4 Issue244Exception
4 readyException
5 HttpException
5 MethodProphecyException
5 NotFoundHttpException
5 ProcessTimedOutException
5 UnsupportedOperationException
5 ValidationException
6 CommandNotFoundException
6 ErrorException
6 FileException
6 NotFoundResourceException
6 OutOfBoundsException
6 Swift_Plugins_Pop_Pop3Exception
6 Swift_RfcComplianceException
7 FileNotFoundException
7 MissingExtensionException
7 UnsatisfiedDependencyException
8 Swift_TransportException
12 UnexpectedValueException
14 Swift_IoException
15 DomainException
15 ExpressionErrorException
15 PHPUnit_Framework_ExpectationFailedException
16 Swift_SwiftException
17 InvalidResourceException
24 FatalErrorException
28 BadMethodCallException
31 PHPUnit_Framework_MockObject_RuntimeException
36 ParseException
48 PHPUnit_Framework_Exception
133 LogicException
212 RuntimeException
395 InvalidArgumentException

7年前 评论

@秦 卧槽,这么多

7年前 评论
朕略显ぼうっと萌

PHP手册上

/**
 * Exception thrown when an illegal index was requested. This represents
 * errors that should be detected at compile time.
 * @link http://php.net/manual/en/class.outofrangeexception.php
 */
class OutOfRangeException extends LogicException {
}

/**
 * Exception thrown if a value is not a valid key. This represents errors
 * that cannot be detected at compile time.
 * @link http://php.net/manual/en/class.outofboundsexception.php
 */
class OutOfBoundsException extends RuntimeException {
}

你貌似写错了一个地方 「OutOfRangeException」 没写「OutOfBoundsException」写了两次

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!