Slim3/DRY - 如何在不重复代码的情况下正确处理 errors/exceptions?
Slim3/DRY - How to handle errors/exceptions correctly without duplicating code?
我正在使用 Slim3 开发一个相当大的 JSON API。我的 controllers/actions 目前充斥着以下内容:
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'Username or password was incorrect'
]);
在应用程序的某些点上,任何事情都可能出错,响应需要适当。但有一点很常见,就是错误响应总是相同的。 status
始终是 error
,data
是可选的(在表单验证错误的情况下 data
将包含这些错误)并且 message
设置为指示API 的用户或消费者出了什么问题。
我闻到了代码重复的味道。如何减少代码重复?
从我的头顶开始,我能想到的就是创建一个自定义异常,比如 App\Exceptions\AppException
接受选项 data
并且 message
将从 $e->getMessage()
.
<?php
namespace App\Exceptions;
class AppException extends Exception
{
private $data;
public function __construct($message, $data = null, $code = 0, $previous = null)
{
$this->data = $data;
parent::__construct($message, $code, $previous);
}
public function getData()
{
return $this->data;
}
}
接下来创建中间件调用 $next
包装在 try/catch:
$app->add(function($request, $response, $next) {
try {
return $next($request, $response);
}
catch(\App\Exceptions\AppException $e)
{
$container->Logger->addCritical('Application Error: ' . $e->getMessage());
return $response->withJson([
'status' => 'error',
'data' => $e->getData(),
'message' => $e->getMessage()
]);
}
catch(\Exception $e)
{
$container->Logger->addCritical('Unhandled Exception: ' . $e->getMessage());
$container->SMSService->send(getenv('ADMIN_MOBILE'), "Shit has hit the fan! Run to your computer and check the error logs. Beep. Boop.");
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'It is not possible to perform this action right now'
]);
}
});
现在我在代码中要做的就是 throw new \App\Exceptions\AppException("Username or password incorrect", null)
.
我唯一的问题是感觉我使用异常的原因不对,这可能会使调试变得更加困难。
关于减少重复和清理错误响应有什么建议吗?
您可以通过创建输出 JSON.
的错误处理程序来实现类似的类似结果
namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
final class ApiError extends \Slim\Handlers\Error
{
public function __invoke(Request $request, Response $response, \Exception $exception)
{
$status = $exception->getCode() ?: 500;
$data = [
"status" => "error",
"message" => $exception->getMessage(),
];
$body = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
return $response
->withStatus($status)
->withHeader("Content-type", "application/json")
->write($body);
}
}
您还必须配置 Slim 以使用您的自定义错误处理程序。
$container = $app->getContainer();
$container["errorHandler"] = function ($container) {
return new Slim\Handlers\ApiError;
};
检查 Slim API Skeleton 示例实施。
我正在使用 Slim3 开发一个相当大的 JSON API。我的 controllers/actions 目前充斥着以下内容:
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'Username or password was incorrect'
]);
在应用程序的某些点上,任何事情都可能出错,响应需要适当。但有一点很常见,就是错误响应总是相同的。 status
始终是 error
,data
是可选的(在表单验证错误的情况下 data
将包含这些错误)并且 message
设置为指示API 的用户或消费者出了什么问题。
我闻到了代码重复的味道。如何减少代码重复?
从我的头顶开始,我能想到的就是创建一个自定义异常,比如 App\Exceptions\AppException
接受选项 data
并且 message
将从 $e->getMessage()
.
<?php
namespace App\Exceptions;
class AppException extends Exception
{
private $data;
public function __construct($message, $data = null, $code = 0, $previous = null)
{
$this->data = $data;
parent::__construct($message, $code, $previous);
}
public function getData()
{
return $this->data;
}
}
接下来创建中间件调用 $next
包装在 try/catch:
$app->add(function($request, $response, $next) {
try {
return $next($request, $response);
}
catch(\App\Exceptions\AppException $e)
{
$container->Logger->addCritical('Application Error: ' . $e->getMessage());
return $response->withJson([
'status' => 'error',
'data' => $e->getData(),
'message' => $e->getMessage()
]);
}
catch(\Exception $e)
{
$container->Logger->addCritical('Unhandled Exception: ' . $e->getMessage());
$container->SMSService->send(getenv('ADMIN_MOBILE'), "Shit has hit the fan! Run to your computer and check the error logs. Beep. Boop.");
return $response->withJson([
'status' => 'error',
'data' => null,
'message' => 'It is not possible to perform this action right now'
]);
}
});
现在我在代码中要做的就是 throw new \App\Exceptions\AppException("Username or password incorrect", null)
.
我唯一的问题是感觉我使用异常的原因不对,这可能会使调试变得更加困难。
关于减少重复和清理错误响应有什么建议吗?
您可以通过创建输出 JSON.
的错误处理程序来实现类似的类似结果namespace Slim\Handlers;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
final class ApiError extends \Slim\Handlers\Error
{
public function __invoke(Request $request, Response $response, \Exception $exception)
{
$status = $exception->getCode() ?: 500;
$data = [
"status" => "error",
"message" => $exception->getMessage(),
];
$body = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
return $response
->withStatus($status)
->withHeader("Content-type", "application/json")
->write($body);
}
}
您还必须配置 Slim 以使用您的自定义错误处理程序。
$container = $app->getContainer();
$container["errorHandler"] = function ($container) {
return new Slim\Handlers\ApiError;
};
检查 Slim API Skeleton 示例实施。