【问题标题】:PHP try/catch and fatal errorPHP try/catch 和致命错误
【发布时间】:2024-01-21 21:52:01
【问题描述】:

我正在使用以下脚本来使用 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;
}

问题来了:

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

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

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

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

也就是说,脚本崩溃了,try/catch 好像也没用了。你知道为什么第二次 try/catch 不起作用以及如何解决吗?

感谢您的帮助!

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

【问题讨论】:

    标签: php try-catch fatal-error


    【解决方案1】:

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

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

    PDO如果无法建立连接会抛出异常。您的具体问题是 $db 在您尝试使用它调用方法时未定义,因此您得到一个致命的空指针(有点)。而不是像其他人建议的那样跳过if ($db == null) 箍,您应该只修复您的代码以确保始终在您需要它时定义$db,或者有一种不那么脆弱的方式来确保数据库连接在使用它的代码。

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

    【讨论】:

    • 好的,感谢您的解释。如果与数据库的连接失败,我将停止生成请求的页面。最终用户更容易并且可能更容易理解(而不是在通知框堆叠时出错)。
    • set_error_handler 可能不适用于某些错误 - 如果是这样,您可以尝试 register_shutdown_function 代替讨论的 in another thread on SO
    • 你能帮我吗>错误>致命错误:不能使用try without catch or finally in C:\wamp\www\anusthana\andro.php on line 55 justpaste.it/74cqb@Explosion Pills跨度>
    【解决方案2】:

    在 PHP7 中,we now can using try catch fatal error 工作简单

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

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

    【讨论】:

      【解决方案3】:

      如果$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;
      }
      

      希望这对其他人有帮助!

      【讨论】:

      • 你能帮帮我吗> 错误 > 致命错误:不能使用 try without catch or finally in C:\wamp\www\anusthana\andro.php on line 55 justpaste.it/74cqb@Imabot
      • 找到了try关键字,但没有找到catch。如果您添加了 catch 关键字,请检查您的大括号。
      • 已解决。只需添加 catch(Exception $e){ $GLOBALS['errors'][] = $e; }
      【解决方案4】:

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

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

      这将确保您可以使用数据库实例。

      【讨论】:

      • 有没有办法避免if($db) { try{...} catch{...} } ?对于每个请求都必须这样做并不是很好......
      • 我不知道你的代码是否在函数中,但我想在这个test.php中你首先连接到数据库然后做其他事情,所以在你第一个try .. catch之后打开连接的块,您可以添加if(!$db) return;if (!$db) die('Could not connect to database')。如果代码执行通过,您可以安全地使用$db 变量,而无需不断检查它是否存在。
      • @Kosta 如果存在--read-only 的数据库但正在尝试写入(插入),这将不起作用。这是我目前的情况
      【解决方案5】:

      尝试添加以下 if 语句:

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

      【讨论】:

      • 我不想使用die() 函数,因为我仍然想运行脚本的以下部分。所有请求都在返回给客户端之前完成,所以如果出现错误,我可以向最终用户显示友好的错误。
      • @Ploppe 然后您只需省略 die 部分并使用 else 部分来显示用户友好的错误。您需要做的基本上是检测连接是否可用。所以检查 $db 实例是必不可少的。
      • 事实上,几乎所有的答案都与评估 $db 实例的思路相同。
      【解决方案6】:
      try{
      if(!is_null($db))
      {
          $query = $db->prepare("INSERT INTO users (...) VALUES (...);");
          $query->execute(array(
              '...' => $...,
              '...' => $...
          ));
      }
      }
      catch(Exception $e){
          $GLOBALS['errors'][] = $e;
      }
      

      【讨论】:

        最近更新 更多