PHP 怎么PHP 异常处理

wen PHP项目 1

本文目录导读:

PHP 怎么PHP 异常处理

  1. 基本语法
  2. 内置异常类
  3. 自定义异常类
  4. 多种异常捕获
  5. 全局异常处理
  6. 错误与异常的区别
  7. 错误转换为异常
  8. 最佳实践
  9. 常见异常处理方法
  10. 异常处理模板

在 PHP 中,异常处理是一种用于管理程序运行时错误的机制,它允许你优雅地处理错误情况,而不是让脚本直接终止,PHP 使用 trycatchthrowfinally 关键字来实现异常处理。


基本语法

1 抛出异常 (throw)

function divide($a, $b) {
    if ($b == 0) {
        throw new InvalidArgumentException("除数不能为零");
    }
    return $a / $b;
}

2 捕获异常 (try-catch)

try {
    $result = divide(10, 0);
    echo $result;
} catch (InvalidArgumentException $e) {
    echo "发生错误: " . $e->getMessage();
}

3 finally 块(可选,PHP 5.5+)

try {
    // 可能抛出异常的代码
    $file = fopen("test.txt", "r");
    // ...
} catch (Exception $e) {
    echo "捕获异常: " . $e->getMessage();
} finally {
    // 无论是否发生异常都会执行
    if (isset($file)) {
        fclose($file);
    }
}

内置异常类

PHP 提供了多个内置异常类:

// 所有异常的基类
Exception
// 逻辑相关的异常
LogicException
    - BadFunctionCallException
    - BadMethodCallException
    - DomainException
    - InvalidArgumentException
    - LengthException
    - OutOfRangeException
// 运行时相关的异常
RuntimeException
    - OutOfBoundsException
    - OverflowException
    - RangeException
    - UnderflowException
    - UnexpectedValueException

自定义异常类

class CustomException extends Exception {
    public function customErrorMessage() {
        $errorMsg = "错误行号: " . $this->getLine() . 
                    " 文件: " . $this->getFile() . 
                    " 消息: " . $this->getMessage();
        return $errorMsg;
    }
}
try {
    throw new CustomException("这是一个自定义异常");
} catch (CustomException $e) {
    echo $e->customErrorMessage();
}

多种异常捕获

try {
    // 可能抛出不同类型异常的代码
    $input = "abc";
    if (!is_numeric($input)) {
        throw new InvalidArgumentException("输入必须是数字");
    }
    if ($input < 0) {
        throw new OutOfRangeException("数字不能为负数");
    }
} catch (InvalidArgumentException $e) {
    echo "输入错误: " . $e->getMessage();
} catch (OutOfRangeException $e) {
    echo "范围错误: " . $e->getMessage();
} catch (Exception $e) {
    // 捕获所有其他异常
    echo "其他错误: " . $e->getMessage();
}

全局异常处理

1 set_exception_handler

function myExceptionHandler($exception) {
    echo "未捕获的异常: " . $exception->getMessage();
    // 可以记录日志、发送邮件等
}
set_exception_handler("myExceptionHandler");
// 如果这个异常没有被捕获,将调用自定义的异常处理器
throw new Exception("未捕获的异常");

2 restore_exception_handler

// 恢复之前的异常处理器
restore_exception_handler();

错误与异常的区别

特性 错误 (Error) 异常 (Exception)
触发方式 由 PHP 引擎自动触发 通过 throw 关键字手动抛出
处理机制 set_error_handler() try-catch
是否可恢复 大多数错误不可恢复 可以通过 catch 处理并恢复
示例 语法错误、内存不足等 业务逻辑错误、参数校验失败等

错误转换为异常

function errorToException($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        // 这个错误级别不在 error_reporting 范围内
        return false;
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
}
// 设置错误处理函数
set_error_handler("errorToException");
try {
    // 触发一个警告
    $result = 1 / 0; // Division by zero
} catch (ErrorException $e) {
    echo "捕获到错误: " . $e->getMessage();
}

最佳实践

class Database {
    public function connect($host, $user, $pass) {
        $conn = @mysqli_connect($host, $user, $pass);
        if (!$conn) {
            throw new RuntimeException("数据库连接失败: " . mysqli_connect_error());
        }
        return $conn;
    }
}
class Application {
    private $db;
    public function run() {
        try {
            $this->db = new Database();
            $conn = $this->db->connect("localhost", "root", "password");
            // 业务逻辑...
        } catch (RuntimeException $e) {
            // 记录日志
            error_log($e->getMessage());
            // 向用户显示友好的错误消息
            echo "系统暂时无法访问,请稍后再试。";
            // 可选的:发送邮件通知管理员
            // mail("admin@example.com", "数据库错误", $e->getMessage());
        } finally {
            // 清理资源
            if (isset($conn)) {
                mysqli_close($conn);
            }
        }
    }
}

常见异常处理方法

1 使用断言

ini_set('assert.exception', 1);
assert(2 > 3, "2 应该大于 3"); // 抛出 AssertionError

2 多层异常处理

function outer() {
    try {
        inner();
    } catch (Exception $e) {
        // 包装异常
        throw new RuntimeException("外层错误", 0, $e);
    }
}
function inner() {
    throw new InvalidArgumentException("内层错误");
}
try {
    outer();
} catch (RuntimeException $e) {
    echo "外层错误: " . $e->getMessage();
    echo "内层错误: " . $e->getPrevious()->getMessage();
}

异常处理模板

<?php
// 配置文件
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
// 设置异常处理器
set_exception_handler(function($exception) {
    // 记录错误日志
    $logMessage = "[" . date('Y-m-d H:i:s') . "] " . 
                  $exception->getMessage() . 
                  " in " . $exception->getFile() . 
                  " on line " . $exception->getLine() . 
                  PHP_EOL;
    error_log($logMessage, 3, '/var/log/php_errors.log');
    // 返回 JSON 响应(如果是 API)
    header('Content-Type: application/json');
    echo json_encode([
        'success' => false,
        'message' => '服务器内部错误'
    ]);
});
try {
    // 主应用程序代码
    // ...
} catch (Exception $e) {
    // 具体的异常处理
}
?>

通过合理使用异常处理机制,你可以让你的 PHP 应用程序更加健壮、易于维护和调试。

抱歉,评论功能暂时关闭!