【问题标题】:How to catch Exceptions correctly in PHP and MongoDB如何在 PHP 和 MongoDB 中正确捕获异常
【发布时间】:2016-08-20 04:21:21
【问题描述】:

我的问题是关于在 PHP 中捕获异常的正确方法。 基于 PHP MongoDB 驱动程序随附的examples,我 已创建以下脚本:

<?php

try {

    $mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
    $query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     

    $rows = $mng->executeQuery("testdb.cars", $query);

    foreach ($rows as $row) {

        echo "$row->name : $row->price\n";
    }

} catch (MongoDB\Driver\Exception\Exception $e) {

    $filename = basename(__FILE__);

    echo "The $filename script has experienced an error.\n"; 
    echo "It failed with the following exception:\n";

    echo "Exception:", $e->getMessage(), "\n";
    echo "In file:", $e->getFile(), "\n";
    echo "On line:", $e->getLine(), "\n";       
}

?>

该示例具有教育意义,旨在在 PHP CLI 上运行。在 PHP CLI 中,我们在控制台上获取所有异常,但出于教学目的,我想在 try/catch 块中捕获异常。

我看到的 Java 代码比 PHP 多,因此,捕获一个通用的 MongoDB\Driver\Exception\Exception 对我来说并不好。在 Java 中,我们捕获特定的异常,并为不同类型的异常提供多个 try/catch 块。

驱动有以下例外:

MongoDB\Driver\Exception\AuthenticationException
MongoDB\Driver\Exception\BulkWriteException 
MongoDB\Driver\Exception\ConnectionException 
MongoDB\Driver\Exception\ConnectionTimeoutException 
MongoDB\Driver\Exception\Exception 
MongoDB\Driver\Exception\ExecutionTimeoutException 
MongoDB\Driver\Exception\InvalidArgumentException 
MongoDB\Driver\Exception\LogicException 
MongoDB\Driver\Exception\RuntimeException 
MongoDB\Driver\Exception\SSLConnectionException 
MongoDB\Driver\Exception\UnexpectedValueException 
MongoDB\Driver\Exception\WriteException

这是一种在 PHP 中捕获异常的合理方式吗?

【问题讨论】:

    标签: php mongodb exception-handling try-catch


    【解决方案1】:

    添加多个 catch 语句我认为这是比 switch 更好的方法。但是,如果异常不是来自这些带有开关的类,那么您应该有一个默认情况,并且如果您使用多个捕获来做到这一点。

    try {
    
    $mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
    $query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     
    
    $rows = $mng->executeQuery("testdb.cars", $query);
    
    foreach ($rows as $row) {
    
        echo "$row->name : $row->price\n";
    }
    
    } catch (MongoDB\Driver\Exception\AuthenticationException $e) {
        echo "AuthenticationException:", $e->getMessage(), "\n";
    
    } catch (MongoDB\Driver\Exception\ConnectionException $e) {
        echo "ConnectionException:", $e->getMessage(), "\n";
    
    } catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
        echo "ConnectionTimeoutException:", $e->getMessage(), "\n";
    
    }catch (\Exception $e) {
           echo "Exception:", $e->getMessage(), "\n";
    }
    

    【讨论】:

      【解决方案2】:

      你可以添加多个catch语句

      <?php
      
      try {
      
          $mng = new MongoDB\Driver\Manager("mongodb://localhost:2717");
          $query = new MongoDB\Driver\Query([], ['sort' => [ 'name' => 1], 'limit' => 5]);     
      
          $rows = $mng->executeQuery("testdb.cars", $query);
      
          foreach ($rows as $row) {
      
              echo "$row->name : $row->price\n";
          }
      
      } catch (MongoDB\Driver\Exception\AuthenticationException $e) {
      
          echo "Exception:", $e->getMessage(), "\n";
      } catch (MongoDB\Driver\Exception\ConnectionException $e) {
      
          echo "Exception:", $e->getMessage(), "\n";
      } catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
      
          echo "Exception:", $e->getMessage(), "\n";
      }
      
      ?>
      

      【讨论】:

      • 这是在 Java 中完成的。问题是这是否是正确的方法。 (我没有在 PHP 中看到那样的代码。)MongoDB\Driver\Exception\Exception 也捕获了 ConnectionTimeoutException 所以也许这样做是多余的。
      • 是的,它是 Java 方式,在 PHP 中也是如此。有关更多信息,您可以查看php.net/manual/en/language.exceptions.php。 MongoDB\Driver\Exception\Exception 是捕获所有异常的通用类,必须用作 catch 语句中未明确捕获的异常的后备。
      【解决方案3】:

      如何在 catch 部分放置一个 switch 语句,并使用 instanceof 语言结构或 get_class() 函数确定异常的类型?

      例如:

      [...]
      
      } catch(\Exception $e) {
         switch (get_class($e)) {
           case 'MongoDB\Driver\Exception\AuthenticationException':
             // do stuff
             break;
      
           case 'MongoDB\Driver\Exception\BulkWriteException':
           //etc, etc...
         }
      }
      

      首先,我会检查 get_class() 的返回值,以确保您将结果与确切的异常名称进行比较。

      【讨论】:

      • 我们可以这样做,但这是在 PHP 中捕获异常的推荐方法吗?如果有,为什么?
      猜你喜欢
      • 2020-01-29
      • 2015-10-09
      • 1970-01-01
      • 2016-08-24
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      相关资源
      最近更新 更多