使用自定义ID和自定义消息在PHP中处理错误
我正在进行一个项目,我不想直接向用户抛出错误。相反,我想要定制的错误消息accur 以后我还需要保留一个错误号,以便自定义来自类外部的错误消息,如错误消息数组 所以我做了我自己的东西,我设置了使用自定义ID和自定义消息在PHP中处理错误,php,class,error-handling,Php,Class,Error Handling,我正在进行一个项目,我不想直接向用户抛出错误。相反,我想要定制的错误消息accur 以后我还需要保留一个错误号,以便自定义来自类外部的错误消息,如错误消息数组 所以我做了我自己的东西,我设置了$error=null,然后将error设置为一个数字,这个数字后来会变成一条消息 问题 这种方法有什么缺点吗?我是不是更喜欢尝试/抓住还是别的什么?如果可能的话,我想保持代码简短整洁 在这个简短的代码示例中,错误处理似乎是类的重要组成部分。在我的实际代码中,只有几百行,它不是整个代码的一大部分 我问这个
$error=null
,然后将error设置为一个数字,这个数字后来会变成一条消息
问题
这种方法有什么缺点吗?我是不是更喜欢尝试/抓住还是别的什么?如果可能的话,我想保持代码简短整洁
在这个简短的代码示例中,错误处理似乎是类的重要组成部分。在我的实际代码中,只有几百行,它不是整个代码的一大部分
我问这个问题的原因是,我有一种感觉,在这种情况下,我可能会重新发明轮子。是吗
如果有更好的解决方案,我会很高兴看到代码的样子。我可能会将业务逻辑与错误处理分开,以进一步简化每个部分。通过使用异常,您可以简化业务逻辑;每当遇到不允许的情况时,您只需
抛出一个异常,从而防止进入任何不一致的状态。业务逻辑类不必关心如何进一步处理此错误,它只需要提出错误。然后,您应该围绕业务逻辑类创建一个单独的包装器,该包装器只关心处理任何错误,并将它们格式化为数组或其他类型的响应,这些响应将在别处处理。大致如下:
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*异常
,或者使用ProjectException
捕获其中任何一个异常
通过让方法抛出异常,您可以获得灵活的错误处理可能性。您可以自由地不捕获异常并终止程序,如果您的一个业务需求没有得到满足,这是完全合理的。或者,您可以在准备处理该错误的级别捕获异常,并将其转化为可以执行的有意义的操作
通过将错误消息的生成移动到异常中,可以保持错误类型及其消息的自包含性。只有一个地方可以定义可能发生的错误类型及其错误消息的外观;而不是将其分散到整个代码库中。您仍然可以在UI中自由选择其他错误消息,例如,将不同类型的错误本地化为多种语言;只需检查异常对象的类型
通过使用一个独立的ProjectService
,它关心如何处理这些异常并将其转换为数组响应,可以缩小每个类的范围,使每个类更加灵活和简单
为什么不使用异常…?通过指定您自己的异常类,您可以通过编程简单地区分错误类型,并且它们也包含自己的消息。是的,谢谢!我现在在代码中看到的好处是1。我自己不需要管这些冒泡的事。我可以晚一点赶上。2.我有点惊讶,但实际上我可以减少代码,主要是因为1。
Array
(
[success] =>
[error] => Array
(
[id] => 2
[message] => Another error at level two: 2
)
)
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));