Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php catch语句中函数的错误处理_Php_Oop_Zend Framework_Error Handling_Dry - Fatal编程技术网

Php catch语句中函数的错误处理

Php catch语句中函数的错误处理,php,oop,zend-framework,error-handling,dry,Php,Oop,Zend Framework,Error Handling,Dry,这是一段代码,我想知道是否应该对其进行重构,使其更符合干净的代码实践 这是一个负责退还客户订单的课程 class RefundServiceInvoker { private $_orders; public function refundOrder() { $this->getOrdersFromDB(); //This function gets all orders from DB and sets $_orders fore

这是一段代码,我想知道是否应该对其进行重构,使其更符合干净的代码实践

这是一个负责退还客户订单的课程

class RefundServiceInvoker {

    private $_orders;

    public function refundOrder() {   
        $this->getOrdersFromDB(); //This function gets all orders from DB and sets $_orders
        foreach ($this->_orders as $order) { 
            try {
                $order->refund(); //Some lines may throw an exception when refunded due to some business logic (ex. the order was already shipped)
                $this->updateOrderStatus('refunded')            
            } catch (Exception $e) {                   
                $this->logError($e);
                $this->sendMailToAdmin();
            }
        }
    }
}
当然,这段代码比我的原始代码要简单得多

我的主要问题是如果
$order->return()引发异常,它将被捕获并记录到数据库,然后发送邮件。但是如果
$this->logError($e)本身引发异常?或者如果邮件服务器关闭并引发异常怎么办

如果数据库本身关闭并且
$this->getOrdersFromDB()引发异常

我的第一个解决方案是将所有内容包装在一个大的
try{}catch{}

public function refundOrder() {   
            try {              
            $this->getOrdersFromDB(); //This function gets all orders from DB and sets $_orders
            foreach ($this->_orders as $order) { 

                    $order->refund(); //Some lines may throw an exception when refunded due to some business logic (ex. the order was already shipped)
                    $this->updateOrderStatus('refunded')            
                } catch (Exception $e) {                   
                    $this->logError($e);
                    $this->sendMailToAdmin();
                }
            }
        }
但这意味着如果一个订单失败,那么所有订单都会失败!!我应该为整个函数放置2
try{}catch{}
一个,为每个顺序放置另一个吗?但是在这种情况下,catch中的函数也可能抛出一个不会被捕获的异常

注:

该应用程序是使用Zend framework 1.11.11构建的


提前感谢。

解决这些问题没有灵丹妙药。如果一个函数可以抛出,而您关心它,那么您必须围绕它包装
try
/
catch
——就这么简单

进入细节:在没有更多关于应用程序架构的信息的情况下,评估这种或那种方法的优点是不可能的,但这里有一些一般性的建议:

  • 在致电
    退款订单
    之前检查先决条件。确保订单已成功加载;确保您要操作的订单都是可退款的(尝试退款由于业务逻辑而不可退款的订单的目的是什么?在尝试退款之前不应该通知用户/运营商吗?)
  • 不要使用多个级别的
    尝试
    /
    捕获
    ,但可能不是所有的
    退款订单
    。外部块用于捕获任何真正意外的错误,那么仅在
    returnorder
    内部捕获它们有什么意义呢?你不想在应用程序的其他部分也这样做吗?最里面的
    try
    /
    catch
    是必需的,这样一个不可退款的订单就不会终止整个流程

    • 解决这些问题没有灵丹妙药。如果一个函数可以抛出,而您关心它,那么您必须围绕它包装
      try
      /
      catch
      ——就这么简单

      进入细节:在没有更多关于应用程序架构的信息的情况下,评估这种或那种方法的优点是不可能的,但这里有一些一般性的建议:

      • 在致电
        退款订单
        之前检查先决条件。确保订单已成功加载;确保您要操作的订单都是可退款的(尝试退款由于业务逻辑而不可退款的订单的目的是什么?在尝试退款之前不应该通知用户/运营商吗?)
      • 不要使用多个级别的
        尝试
        /
        捕获
        ,但可能不是所有的
        退款订单
        。外部块用于捕获任何真正意外的错误,那么仅在
        returnorder
        内部捕获它们有什么意义呢?你不想在应用程序的其他部分也这样做吗?最里面的
        try
        /
        catch
        是必需的,这样一个不可退款的订单就不会终止整个流程
      由于
      logError($e)
      sendMailToAdmin()
      可能是在最后手段中使用的函数,通常在try/catch块中,我会确保它们不会引发异常

      function logError($e)
      {
          try
          {
              //your logic that may throw an Exception here
          }
          catch {}
      }
      
      function sendMailToAdmin($e)
      {
          try
          {
              //your logic that may throw an Exception here
          }
          catch {}
      }
      
      由于
      logError($e)
      sendMailToAdmin()
      可能是在最后手段中使用的函数,通常在try/catch块中使用,因此我将确保它们不会引发异常

      function logError($e)
      {
          try
          {
              //your logic that may throw an Exception here
          }
          catch {}
      }
      
      function sendMailToAdmin($e)
      {
          try
          {
              //your logic that may throw an Exception here
          }
          catch {}
      }
      

      如果您需要记录并邮寄每个异常,那么您需要以下内容:

      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            try {
               $this->getOrdersFromDB();
               foreach ($this->_orders as $order) {
                  try {
                     $order->refund();
                  } catch (MyBusinessException $e) {
                     # deals with the problematic $order without stopping the loop
                     $this->logError($e);
                     $this->sendMailToAdmin();
                  }
                  $this->updateOrderStatus('refunded');
               }
            } catch(Exception $e) {
               # deals with unexpected bugs
               $this->logError($e);
               $this->sendMailToAdmin();
            }
         }
      }
      
      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            $this->getOrdersFromDB();
            foreach ($this->_orders as $order) {
               try {
                  $order->refund();
               } catch (MyBusinessException $e) {
                  # deals with the problematic $order without stopping the loop
                  $this->logError($e);
                  $this->sendMailToAdmin();
               }
               $this->updateOrderStatus('refunded');
            }
         }
      }
      
      但您必须在log和mail方法中加入try/catch,以防止它们在服务器脱机时抛出任何异常。如果不这样做,当日志/邮件失败时,$orders循环将停止

      如果您只需要在return()方法中记录/发送您的业务异常,那么您需要如下内容:

      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            try {
               $this->getOrdersFromDB();
               foreach ($this->_orders as $order) {
                  try {
                     $order->refund();
                  } catch (MyBusinessException $e) {
                     # deals with the problematic $order without stopping the loop
                     $this->logError($e);
                     $this->sendMailToAdmin();
                  }
                  $this->updateOrderStatus('refunded');
               }
            } catch(Exception $e) {
               # deals with unexpected bugs
               $this->logError($e);
               $this->sendMailToAdmin();
            }
         }
      }
      
      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            $this->getOrdersFromDB();
            foreach ($this->_orders as $order) {
               try {
                  $order->refund();
               } catch (MyBusinessException $e) {
                  # deals with the problematic $order without stopping the loop
                  $this->logError($e);
                  $this->sendMailToAdmin();
               }
               $this->updateOrderStatus('refunded');
            }
         }
      }
      
      任何其他异常都会导致http 500–内部服务器错误页面,这通常是您想要的,因为这是一个意外错误


      还有其他方法可以处理此问题,但正如您所看到的,这取决于您的需要。

      如果您需要记录并邮寄每个异常,那么您需要以下内容:

      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            try {
               $this->getOrdersFromDB();
               foreach ($this->_orders as $order) {
                  try {
                     $order->refund();
                  } catch (MyBusinessException $e) {
                     # deals with the problematic $order without stopping the loop
                     $this->logError($e);
                     $this->sendMailToAdmin();
                  }
                  $this->updateOrderStatus('refunded');
               }
            } catch(Exception $e) {
               # deals with unexpected bugs
               $this->logError($e);
               $this->sendMailToAdmin();
            }
         }
      }
      
      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            $this->getOrdersFromDB();
            foreach ($this->_orders as $order) {
               try {
                  $order->refund();
               } catch (MyBusinessException $e) {
                  # deals with the problematic $order without stopping the loop
                  $this->logError($e);
                  $this->sendMailToAdmin();
               }
               $this->updateOrderStatus('refunded');
            }
         }
      }
      
      但您必须在log和mail方法中加入try/catch,以防止它们在服务器脱机时抛出任何异常。如果不这样做,当日志/邮件失败时,$orders循环将停止

      如果您只需要在return()方法中记录/发送您的业务异常,那么您需要如下内容:

      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            try {
               $this->getOrdersFromDB();
               foreach ($this->_orders as $order) {
                  try {
                     $order->refund();
                  } catch (MyBusinessException $e) {
                     # deals with the problematic $order without stopping the loop
                     $this->logError($e);
                     $this->sendMailToAdmin();
                  }
                  $this->updateOrderStatus('refunded');
               }
            } catch(Exception $e) {
               # deals with unexpected bugs
               $this->logError($e);
               $this->sendMailToAdmin();
            }
         }
      }
      
      class RefundServiceInvoker {
      
         private $_orders;
      
         public function refundOrder() {
            $this->getOrdersFromDB();
            foreach ($this->_orders as $order) {
               try {
                  $order->refund();
               } catch (MyBusinessException $e) {
                  # deals with the problematic $order without stopping the loop
                  $this->logError($e);
                  $this->sendMailToAdmin();
               }
               $this->updateOrderStatus('refunded');
            }
         }
      }
      
      任何其他异常都会导致http 500–内部服务器错误页面,这通常是您想要的,因为这是一个意外错误

      还有其他方法可以处理这个问题,但正如您所看到的,这取决于您的需要。

      是否
      $this->logError()
      确实引发过异常?看起来这可能不是最佳实践,您可能很容易陷入无限循环。您真正需要做的是决定如果错误日志记录/管理电子邮件发送失败,您希望应用程序做什么。如果您只是忽略错误并继续,请不要抛出这些方法中的任何异常。如果您希望使用堆栈跟踪终止,请不要捕获异常。如果你想知道如何处理这种情况,可以使用内部的try/catch。嗯…基本上是的,