【问题标题】:Why doesn't PHP catch a "Class not found" error?为什么 PHP 没有捕捉到“找不到类”错误?
【发布时间】:2010-12-12 11:01:28
【问题描述】:

在以下示例中,如果该类不存在,我想捕获错误并改为创建一个Null 类。

但尽管我有 try/catch 语句,PHP 只是告诉我 Class 'SmartFormasdfasdf' not found

如何让 PHP 捕获“找不到类”错误?

<?php
class SmartFormLogin extends SmartForm {
    public function render() {
        echo '<p>this is the login form</p>';
    }
}

class SmartFormCodeWrapper extends SmartForm {
    public function render() {
        echo '<p>this is the code wrapper form</p>';
    }
}

class SmartFormNull extends SmartForm {
    public function render() {
        echo '<p>the form "' . htmlentities($this->idCode) . '" does not exist</p>';
    }
}

class SmartForm {

    protected $idCode;

    public function __construct($idCode) {
        $this->idCode = $idCode;
    }

    public static function create($smartFormIdCode) {
        $className = 'SmartForm' . $smartFormIdCode;
        try {
            return new $className($smartFormIdCode);
        } catch (Exception $ex) {
            return new SmartFormNull($smartformIdCode);
        }
    }
}

$formLogin = SmartForm::create('Login');
$formLogin->render();
$formLogin = SmartForm::create('CodeWrapper');
$formLogin->render();
$formLogin = SmartForm::create('asdfasdf');
$formLogin->render();
?>

解决方案:

谢谢@Mchl,我当时就是这样解决的:

public static function create($smartFormIdCode) {
  $className = 'SmartForm' . $smartFormIdCode;
  if(class_exists($className)) {
    return new $className($smartFormIdCode);
  } else {
    return new SmartFormNull($smartFormIdCode);
  }
} 

【问题讨论】:

    标签: php try-catch


    【解决方案1】:

    因为这是一个致命错误。使用 class_exists() 函数检查类是否存在。

    另外:PHP 不是 Java - 除非您重新定义默认错误处理程序,否则它将引发错误而不抛出异常。

    【讨论】:

    • 我忘了,PHP 的 try/get 功能只是通过让您抛出自己的错误来帮助您构建自己的异常处理,但不会像在 C#/Java 中那样自己捕获错误。
    • 请参阅php.net/manual/en/class.errorexception.php 例如,了解如何将所有(致命除外)错误“重写”为异常。此外,正如其他建议的那样,从 5.3 开始,您可能希望在找不到包含给定类的文件时使用自动加载器引发异常。
    • @Edward - 它当然可以让您捕获异常,但几乎所有 PHP 原生的东西都不会抛出异常,只会抛出错误。您可以通过定义自己的 error_handler 并使用 ErrorException 抛出异常来轻松解决此问题(请参阅au.php.net/errorexception 和那里的示例)。这很容易将 PHP 的原生错误系统切换到一个有用的基于异常的系统,该系统与 throw/try/catch 等配合得非常好。
    【解决方案2】:

    老问题,但在 PHP7 中这是一个可捕获的异常。虽然我仍然认为class_exists($class) 是一种更明确的方式。但是,您可以使用新的 \Throwable 异常类型执行 try/catch 块:

    $className = 'SmartForm' . $smartFormIdCode;
    try {
        return new $className($smartFormIdCode);
    } catch (\Throwable $ex) {
        return new SmartFormNull($smartformIdCode);
    }
    

    【讨论】:

    • 另外,如果您想更具体地了解您正在捕获的内容,您可以捕获 \Error 类型(经过测试可在 PHP 7.1 中使用)。这将使您的代码更容易改变 PHP 语言的发展方式,但也不太可能捕获您不希望它捕获的东西。如果你有很好的自动化测试,你应该能够摆脱更具体的版本,因为如果 PHP 突然开始为此抛出不同的类型,你的测试将会失败。
    • 谢谢。完美的答案。
    【解决方案3】:

    php >= 7.0

    php 可以将 'class not found' 捕获为 Throwable

    try {
            return new $className($smartFormIdCode);
    } catch (\Throwable $ex) {
            return new SmartFormNull($smartformIdCode);
    }
    

    【讨论】:

      【解决方案4】:

      在尝试实例化它之前,您需要使用class_exists 来查看该类是否存在。

      顺便说一句,如果您使用的是类自动加载器,请务必将第二个参数设置为 true。

      【讨论】:

        【解决方案5】:

        因为当您创建不存在类的新对象时,php 会发出致命错误。要使其工作,您需要 php >= 5.3 和 autoload 函数,您应该尝试在其中查找具有类定义的文件或抛出您的自定义异常。

        【讨论】:

        • a) 自动加载是错误的方法 - 请参阅 au.php.net/manual/en/function.spl-autoload-register.php 和 b) 它不需要 PHP 5.3
        • 在自动加载器中抛出异常确实需要 5.3。只要您知道自己在做什么,就没有任何“错误”(即当自动加载队列中有更多自动加载器时抛出异常有点愚蠢)。
        • @El Yobo - 你能详细说明自动加载有什么问题吗? spl 函数的作用相同,唯一的区别是它允许您提供更多函数来运行以搜索正确的文件。 Ans 至于 b),正如 Mchl 所说,您仍然需要 php 5.3 才能使其抛出异常。
        猜你喜欢
        • 2018-07-02
        • 2019-05-16
        • 2018-12-25
        • 2012-01-06
        • 2021-07-25
        • 2017-07-25
        • 2012-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多