PHP尝试/捕获和致命错误

时间:2012-10-17 06:35:37

标签: php try-catch fatal-error

我正在使用以下脚本使用PHP来使用数据库:

try{
    $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}
catch(Exception $e){
    $GLOBALS['errors'][] = $e;
}

现在,我想使用此数据库句柄来使用此代码执行请求:

try{
    $query = $db->prepare("INSERT INTO users (...) VALUES (...);");
    $query->execute(array(
        '...' => $...,
        '...' => $...
    ));
}
catch(Exception $e){
    $GLOBALS['errors'][] = $e;
}

问题在于:

  • 当与DB的连接正常时,一切正常,
  • 当连接失败但我没有使用数据库时,我有$GLOBALS['errors'][]数组,之后脚本仍在运行,
  • 当与DB的连接失败时,我收到以下致命错误:
  

注意:未定义的变量:第32行的C:\ xampp \ htdocs [...] \ test.php中的db

     

致命错误:在第32行的C:\ xampp \ htdocs [...] \ test.php中的非对象上调用成员函数prepare()

注意:第32行是$query = $db->prepare(...)指令。

也就是说,脚本崩溃了,try / catch似乎没用。你知道为什么第二次尝试/捕获不起作用以及如何解决它?

感谢您的帮助!

编辑:有一些非常好的回复。我已经验证了一个不是我想要做的,但这可能是最好的方法。

7 个答案:

答案 0 :(得分:27)

try / catch块仅适用于抛出异常(throw Exception或必须调用Exception的子类)。使用try / catch无法捕获致命错误。

如果您的数据库连接无法建立,我认为这是致命的,因为您可能需要您的数据库在页面上执行任何有意义的操作。

如果无法建立连接,

PDO将抛出异常。您的具体问题是当您尝试使用它调用方法时未定义$db,因此您获得了一个致命的空指针(类型)。不要像其他人建议的那样跳过if ($db == null)箍,你应该修改你的代码,以确保在你需要的时候总是定义$db,或者确保数据库连接不那么脆弱。在使用它的代码中可用。

如果你真的想“捕获”致命错误,请使用set_error_handler,但这仍然会在致命错误上停止脚本执行。

答案 1 :(得分:7)

在PHP7中,我们现在可以通过简单的工作使用try catch致命错误

try {
   do some thing evil
} catch (Error $e) {
   echo 'Now you can catch me!';
}

但是通常,我们应该避免使用catch错误,因为它涉及错过属于程序员职责的代码:-)

答案 2 :(得分:1)

如果数据库连接失败,您第一个$db块中的try .. catch将为空。这就是为什么以后你不能使用非对象的成员,在你的情况$db->prepare(...)。在使用之前添加

if ($db) {
    // other try catch statement
}

这将确保您使用db实例来处理它。

答案 3 :(得分:0)

为什么使用try ... catch语句来声明这一点。替换这个:

try{
    $db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options);
}

使用:

$db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options) or die("Cannot Create PDO!");

或以你的方式:

$db = new PDO('mysql:host='.$host.';port='.$port.';dbname='.$db, $user, $pass, $options) or ($GLOBALS['errors'][] = "Cannot Create PDO!");

答案 4 :(得分:0)

尝试添加以下if语句:

if ($db) {
    $query = $db->prepare("INSERT INTO users (...) VALUES (...);");
    $query->execute(....);
}
else die('Connection lost');

答案 5 :(得分:0)

try{
if(!is_null($db))
{
    $query = $db->prepare("INSERT INTO users (...) VALUES (...);");
    $query->execute(array(
        '...' => $...,
        '...' => $...
    ));
}
}
catch(Exception $e){
    $GLOBALS['errors'][] = $e;
}

答案 6 :(得分:0)

如果$db为空,我不会报告有关测试的内容。只需添加一个“干净”的解决方案就是在与数据库的连接失败时人为地创建异常:

if ($db == NULL) throw new Exception('Connection failed.');

try - catch中插入上一行,如下所示:

try{

    // This line create an exception if $db is empty
    if ($db == NULL) throw new Exception('Connection failed.');


    $query = $db->prepare("INSERT INTO users (...) VALUES (...);");
    $query->execute(array(
        '...' => $...,
        '...' => $...
    ));
}
catch(Exception $e){
    $GLOBALS['errors'][] = $e;
}

希望这会有所帮助!