【问题标题】:Custom PDO Error try/catch自定义 PDO 错误尝试/捕获
【发布时间】:2013-11-18 06:14:47
【问题描述】:

目前,当我的 SQL 出现错误时,它会抛出如下所示的传统错误:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax...|

我知道我可以通过将每个 SQL 例程包装在 try/catch 块中来实现我想要的,但这似乎有点冗长:

class ProductsModel extends Model {

  function __construct()
  {
    parent::__construct();
  }

 public function setName($name, $productId)
  {
    $SQL = 'UPDATE products SET name = ? WHERE id = ?';
    try{
    $r = $this->db->prepare($SQL);
    $r->execute(array($name, $productId));
    }catch(PDOException $e) {
      echo 'Error!';
    }
  }
}

有没有办法为所有 SQL 查询自动完成这项工作?

【问题讨论】:

  • 为什么客户端知道它正在发生 SQL 查询这一事实?您真正想向客户传达什么?如果您想指示失败返回 500 服务器错误状态代码 - 使用状态代码客户端不应该知道服务器内部。此外,像这样捕获和抑制所有错误是非常糟糕的做法。相反,如果它们异常处理它们,则在调用 setName 的代码中处理它们,或者以一种传达它失败的方式定义合同是一个合法的结果(让它返回一个布尔值)例如。盲目压制总是不好的。
  • 老兄,您接受了与您的问题相矛盾的答案。 -1
  • @YourCommonSense 我会接受你的回答,因为它更具教育意义,但它已被锁定:/
  • 最好接受韦恩的说法——他是第一个直接准确回答你的问题的人——“如何在一个地方进行任何异常处理”——正是你所要求的。

标签: php mysql pdo error-handling


【解决方案1】:

是的,不,你不应该这样做。

应该做的是在函数内部捕获它,而是将方法调用包装在更高级别内用 catch 块。即:

try {
    $productsModel->setName("name", 42);
}
catch (PDOException $e) {
    //Do something, 500 error code, whatever
}

那是因为,只有当您尝试访问数据库时,您才知道在失败时要做什么

这个:

  • 让您的方法更简洁,无需在方法内部进行错误处理。
  • 为您提供灵活性。在某些情况下,您可能希望在失败时抛出 500 错误,而在另一种情况下,您可能希望将 JSON 对象返回给 AJAX 调用。

【讨论】:

  • 我会考虑,对我来说听起来不错,但有人可以解释否决票,因为我想知道你为什么不同意吗?
  • 我也是+1。设计为“一刀切”的解决方案通常会做出太多假设,最终您不得不提供覆盖全局解决方案的方法。
  • @imperium2335 否决票可能源于缺乏经验。您代码中的对象传达了您制定的交互方式和契约。如果您的setName 静默失败,则它违反了合同(设置名称)。它必须要么表明情况是异常的(通过投掷),要么传达它是可能的结果(例如通过变为trySetName 并在成功时返回 true,在失败时返回 false。
  • @YourCommonSense 我给你发了一封电子邮件,希望你不介意在那里澄清,因为你觉得这个环境充满敌意或没有建设性。
  • @YourCommonSense:我想通过聊天与您讨论这个问题,上校。如果你愿意,可以邀请我进行私人聊天,如果你可以的话,可以来 PHP 房间。
【解决方案2】:

您可以设置exception handler

<?php
function exception_handler($exception) {
  echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

set_exception_handler('exception_handler');

throw new Exception('Uncaught Exception');
echo "Not Executed\n";
?>

它将捕获所有异常类型,而不仅仅是 PDOExceptions。如果你想专门处理所有 PDOExceptions,你可以这样检查:

function exception_handler($exception) {
   if ($exception instanceof PDOException) {
       echo 'This is a PDOException';
   }
}

【讨论】:

  • 这是一个可怕的想法。
  • @MadaraUchiha 异常处理程序很常见。向用户显示友好的“出现问题”页面不是更好吗?
  • 不,肯定不是。像这样的异常处理程序允许你做你不应该做的事情。一个方法抛出一个异常是有原因的,你应该是一个优秀的开发人员并抓住它,否则,一个致命的错误是合适的。清理你自己的烂摊子,不要依靠魔法来为你做。
  • @MadaraUchiha “一个方法抛出异常是有原因的,你应该是一个优秀的开发人员并抓住它”......嗯,这被称为口袋妖怪异常处理只是因为它是一个案例的“必须抓住他们”。您不必捕获所有异常。
  • @imperium2335 实际上你没有。 AJAX 调用始终知道 HTTP 状态代码,您需要在客户端检查 500 并说“出了点问题”。
【解决方案3】:

实现自己的类 PDO 类:

class MYPDO extends PDO {
  public function query() {
    try {
      call_user_func_array(array($this, 'parent::query'), func_get_args());
    }catch(PDOException $e) {
      echo 'Error!';
    }
  }
}

$db = new MYPDO(...);
$db->query(...);

【讨论】:

  • 这是一个可怕的想法。
  • 我没有投反对票,但我同意这是一个坏主意。如果要抑制所有异常,则不要将 PDO 配置为抛出异常。但最好使用异常并更恰当地捕获它们,这可能意味着在整个应用中根据具体情况做一些不同的事情。
  • 如果你认为这很可怕并不意味着它很可怕。你会得到你想要的一切。只有查询,只有 PDOException。我同意,这不是一个好习惯,但请看看你的问题;)
  • 我不同意:如果有人在问某事并回答此人的问题,那么就会导致制造可怕的事情的局面结束,有人应该说出来并解释原因。很多人会问如何去做他们认为是正确的事情,而不是最初的原因是人们认为这是一个好方法。
  • 如果您只需要在一种方法 (PDO::query) 中捕获一个特定异常 (PDOException),这是一种合乎逻辑的实现方式。
猜你喜欢
  • 1970-01-01
  • 2019-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多