PHP5.3避免嵌套在foreach循环(代码三明治)中的try/catch重复

PHP5.3避免嵌套在foreach循环(代码三明治)中的try/catch重复,php,code-duplication,Php,Code Duplication,我有一个methodA类,它的现有结构如下 function methodA() { $providers = $this->getFirstSetOfProviders(); foreach ($providers as $provider) { try { $this->method1($provider); } catch ( Exception $e ) { // exception handling } }

我有一个methodA类,它的现有结构如下

function methodA() {
  $providers = $this->getFirstSetOfProviders();
  foreach ($providers as $provider) {
    try {
      $this->method1($provider);
    } catch ( Exception $e ) {
      // exception handling
    }
  }

  $providers = $this->getSecondSetOfProviders();
  foreach ($providers as $provider) {
    try {
      $this->method2($provider);
    } catch ( Exception $e ) {
      // exception handling
    }
  }
}
catch子句的内容相同。是否有某种方法来组织代码,以避免重复嵌套在foreach循环中的try/catch结构?从概念上讲,我正在尝试

function methodA() {
  foreach ($providers as $provider) {
    $method1 = function($provider) {
      $this->method1($provider);
    }
    $this->withTryCatch($method1);
  }
  ...
}

function withTryCatch($method) {
  try {
    $method;  // invoke this method somehow
  } catch (Exception $e) {
    // exception handling
  }
}
这看起来类似于,但我不确定如何在php中继续

更新:
try/catch嵌套在foreach循环中,因此当抛出异常时,它将被处理,执行将继续到循环中的下一个迭代,而不是终止循环。

异常的好处在于它们是可以像其他任何对象一样传递的对象。因此,您可以删除重复代码(基本样板除外),而无需做太多更改:

function methodA() {
  try {
      $providers = $this->getFirstSetOfProviders();
      foreach ($providers as $provider) {
          $this->method1($provider);
      }

      $providers = $this->getSecondSetOfProviders();
      foreach ($providers as $provider) {
          $this->method2($provider);
      }
  } catch ( Exception $e ) {
    // exception handling
  }

}
foreach ($providers as $provider) {
    try {
      $this->method1($provider);
    } catch ( Exception $e ) {
      $this->handleException($e);
    }
}
注意:如果您还需要异常处理中的一些上下文(即
$provider
),只需提供
handleException()
更多参数即可

第2部分:重构整个方法

您想知道如何进一步消除重复。我不知道这在您的实际代码中是否有意义,它也可能是过度工程化的。你必须自己决定。下面是模板方法模式的实现。请原谅这个粗俗的名字,但我试着以你为榜样,我不知道你在做什么

abstract class ClassThatDoesThingsWithProviders
{
    public function methodA($providers)
    {
        foreach($provicers as $provider) {
            try {
                $this->methodThatActuallyDoesSomethingWithProvider($provider);
            } catch(Exception $e) {
                $this->handleException($e);
            }
        }
    }
    protected function handleException(Exception $e)
    {
        // handle exception
    }
    abstract protected function methodThatActuallyDoesSomethingWithProvider($provider);
}
class ClassThatDoesThing1WithProviders extends ClassThatDoesThingsWithProviders
{
    protected function methodThatActuallyDoesSomethingWithProvider($provider)
    {
        // this is your method1()
    }
}
class ClassThatDoesThing2WithProviders extends ClassThatDoesThingsWithProviders
{
    protected function methodThatActuallyDoesSomethingWithProvider($provider)
    {
        // this is your method2()
    }
}

class YourOriginalClass
{
    protected $thingsdoer1;
    protected $thingsdoer2;

    public function __construct()
    {
        $this->thingsdoer1 = new ClassThatDoesThing1WithProviders;
        $this->thingsdoer2 = new ClassThatDoesThing2WithProviders;
    }
    public function methodA()
    {
        $this->thingsdoer1->methodA($this->getFirstSetOfProviders());
        $this->thingsdoer2->methodA($this->getSecondSetOfProviders());
    }
}
您可以很容易地将
thingsdoer1
thingsdoer2
组合成一个数组,并且可以将
getFirstSetOfProviders
getSecondSetOfProviders
抽象在一起。我也不知道实际的method1和method2实现依赖于什么,也许你不能像那样提取它们而不破坏内聚


但是,由于我不知道您真正的代码以及您正在做什么,我无法推荐具体的策略,请将我上面的示例作为起点。

感谢您的反馈。但是,我确实需要在foreach循环中嵌套try/catch,这样当某个特定迭代引发异常时,循环将继续到下一个迭代而不是终止。谢谢,这对消除catch子句中的重复非常有帮助。是否有一些方法可以进一步删除try/catch重复?仅是
try
catch
?不,这样做是没有意义的。但是,与复制的
foreach
头部一起,您可以重构整个过程。等待我的编辑。。。