具有自定义ID和自定义消息的PHP中的错误处理



我正在一个项目中,我不想直接向用户投掷错误。相反,我想要自定义消息,以使其正确的错误。

对于以后,我还需要保留一个错误号码才能从类外部自定义错误消息,例如错误消息。

所以我在设置$error = null的地方制作了自己的东西,然后将错误设置为后来成为消息的数字。

问题

这种方法是否有任何缺点?我是否会更好地尝试/捕获或其他东西?如果可能的话,我想简短而整洁。

在此简短代码示例中,错误处理似乎是类的重要组成部分。在我的实际代码几百行中,它不是整个代码的重要组成部分

http://sandbox.onlinephpfunctions.com/code/623B388B7060603BF7F020468AAA9E310F7340CD108

<?php
class Project {
  private $error = null;
  public function callMeFirst($num) {
    $this->nestedLevelOne($num);
    $this->nestedLevelTwo($num);
    $this->setResults();
  }
  public function callMeSecond($num) {
    $this->nestedLevelTwo($num);
    $this->setResults();
  }
  private function nestedLevelOne($num) {
    // Do stuff
    if($num !== 1) {
      $this->error = ['id' => 1, 'value' => $num];
    }
  }
  private function nestedLevelTwo($num) {
    // Do stuff
    if($num !== 20) {
      $this->error = ['id' => 2, 'value' => $num];
    }
  }
  private function message($args) {
    extract($args);
    $message = [
      1 => "Nested level one error: $value",
      2 => "Another error at level two: $value",
    ];
    return ['id' => $id, 'message' => $message[$id]];
  }
  private function setResults() {
    $results['success'] = ($this->error === null) ? true : false;
    if($this->error !== null) {
      $results['error'] = $this->message($this->error);
    }
    $this->results = $results;
  }
}
$project = new Project();
$project->callMeFirst(1);
$project->callMeFirst(2);
print_r($project->results);

它将输出

Array
(
  [success] => 
  [error] => Array
    (
      [id] => 2
        [message] => Another error at level two: 2
    )
)

我问的原因是我有一种感觉,在这种情况下我可能会重新发明轮子。我是吗?

如果有更好的解决方案,我将很高兴看到该代码的外观。

我可能会将业务逻辑与错误处理分开,以简化每个部分。通过使用异常,您可以使业务逻辑更简单;每当您遇到不允许的案例时,您只需throw一个例外,从而完全阻止了任何不一致的状态。业务逻辑类不必关心如何进一步处理此错误,只需提高错误即可。然后,您应该围绕该业务逻辑类创建一个单独的包装器,该类别仅关心处理任何错误并将其格式化为将在其他地方处理的阵列或其他响应。这些行:

class ProjectException extends Exception {
    public function __construct($num) {
        parent::__construct(get_called_class() . ": $num");
    }
}
class NestedLevelOneException extends ProjectException {
    // customise __construct here if desired
}
class NestedLevelTwoException extends ProjectException {}
class Project {
    public function callMeFirst($num) {
        $this->nestedLevelOne($num);
        $this->nestedLevelTwo($num);
    }
    public function callMeSecond($num) {
        $this->nestedLevelTwo($num);
    }
    protected function nestedLevelOne($num) {
        if ($num !== 1) {
            throw new NestedLevelOneException($num);
        }
        // do stuff
    }
    protected function nestedLevelTwo($num) {
        if ($num !== 20) {
            throw new NestedLevelTwoException($num);
        }
        // do stuff
    }
}
class ProjectService {
    protected $project;
    public function __construct(Project $project = null) {
        $this->project = $project ?: new Project;
    }
    public function process($a, $b) {
        try {
            $this->project->callMeFirst($a);
            $this->project->callMeSecond($b);
            return ['success' => true];
        } catch (ProjectException $e) {
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
}
$api = new ProjectService;
print_r($api->process(1, 2));
  1. 通过定义三个单独的例外,您可以在要处理错误的方式和地点方面具有很大的灵活性。您可以专门捕获NestedLevel*Exception,也可以使用ProjectException捕获其中的任何一个。

  2. 通过让您的方法抛出异常,您会获得灵活的错误处理可能性。您可以自由地捕获例外并终止程序,如果您的业务需求之一不满足,这是完全合理的。另外,您可以在准备处理该错误并将其变成有意义的事情的水平上捕获异常。

  3. 通过将错误消息的生成移动到异常中,您可以将错误类型及其消息自动化。正是一个地方,您可以定义可能发生的错误以及其错误消息的外观;而不是将其传播到整个代码库中。而且您仍然可以自由选择UI中的其他错误消息,例如将不同种类的错误本地化为多种语言;只需检查异常对象的类型。

  4. 使用单独的ProjectService,它关心处理这些异常并将其转换为数组响应,您可以缩小每个类的责任,并使每个班级更加灵活,更简单。

最新更新