php - PHP中带有自定义ID和自定义消息的错误处理

标签 php class error-handling

我在一个项目中,我不想直接向用户抛出错误。相反,我想要针对错误的自定义消息。

以后,我还需要保留一个错误号,以便从类外部自定义错误消息,例如错误消息数组。

因此,我做了自己的事情,在其中设置$error = null,然后将error设置为一个后来成为消息的数字。



这种方法有什么缺点吗?我更适合尝试/捕捉还是其他?如果可能的话,我想使代码简短。

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

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

<?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));
  • 通过定义三个单独的异常,您可以在处理错误的方式和位置上获得很大的灵活性。您可以专门捕获NestedLevel*Exception,也可以使用ProjectException捕获它们中的任何一个。
  • 通过让您的方法引发异常,您可以灵活地处理错误。您可以自由地不捕获异常并让程序终止,如果不满足您的业务要求之一,那将是完全合理的。或者,您可以在准备处理该错误的级别上捕获异常,并将其转变为可以采取的有意义的措施。
  • 通过将错误消息的生成移到异常中,可以使错误类型及其消息保持独立。在一个地方,您可以定义可能发生的错误及其错误消息的外观。而不是将其分散在整个代码库中。而且您仍然可以在用户界面中自由选择其他错误消息,例如用于将各种错误本地化为多种语言;只需检查异常对象的类型。
  • 通过使用关心处理那些异常并将其转换为数组响应的单独ProjectService,可以缩小每个类的responsibilities的范围,并使每个类更灵活,更简单。
  • 关于php - PHP中带有自定义ID和自定义消息的错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55217283/

    相关文章:

    PHP - 通过 cron 作业自动检测主目录

    php - MySQL数据库: one media table or one table for images and one for videos?

    node.js - 安装 Angular CLI 时收到错误警告

    javascript - JavaScript 中的错误异常。 TypeError 调用不是一个函数

    php - 有人可以告诉我一种方法来验证我的文本框是否在可以在 php 中激活/单击/打开引导模式之前不为空吗?

    php - 如果值大于/小于 xyz

    c++ - 使用模板参数时的交叉引用

    java - 计划任务永远不会引发异常

    python - 如何在 C++ 中创建可迭代的对象列表?

    ruby - 什么是 Ruby 中的单例类?