PHP try/catch 和致命错误

问题描述 投票:0回答:6

我正在使用以下脚本来使用 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'][]
    数组,并且脚本之后仍在运行,
  • 当与数据库的连接失败时,我收到以下致命错误:

注意:未定义的变量:db in C:\xampp\htdocs[...] est.php on line 32

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

注意: 第 32 行是

$query = $db->prepare(...)
指令。

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

感谢您的帮助!

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

php try-catch fatal-error
6个回答
44
投票

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

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

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


41
投票

try

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

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

如果无法建立连接,

PDO

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

如果您确实想“捕获”致命错误,请使用

set_error_handler

,但这仍然会在出现致命错误时停止脚本执行。


1
投票
如果

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

希望这对其他人有帮助!


0
投票
如果数据库连接失败,第一个

$db

 块中的 
try .. catch
 将为空。这就是为什么以后你不能使用非对象的成员,在你的例子中
$db->prepare(...)
。使用此功能之前添加 

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

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


0
投票
要捕获像

Type error

 这样的致命错误,您可以在 try-catch 构造中使用 
\Throwable

try { // some code } catch (\Throwable $e) { // some code }
    

-1
投票
尝试添加以下 if 语句:

if ($db) { $query = $db->prepare("INSERT INTO users (...) VALUES (...);"); $query->execute(....); } else die('Connection lost');
    
© www.soinside.com 2019 - 2024. All rights reserved.