事情出错了。你无法预测错误,但你可以预料它们。每个 Slim 框架应用程序都有一个错误处理程序,可以接收所有未捕获的 PHP 异常。此错误处理程序还接收当前 HTTP 请求和响应对象。错误处理程序必须准备并返回一个响应对象,以便返回给 HTTP 客户端。
<?php
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
/**
* The routing middleware should be added earlier than the ErrorMiddleware
* Otherwise exceptions thrown from it will not be handled by the middleware
*/
$app->addRoutingMiddleware();
/**
* Add Error Middleware
*
* @param bool $displayErrorDetails -> Should be set to false in production
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
* @param bool $logErrorDetails -> Display error details in error log
* @param LoggerInterface|null $logger -> Optional PSR-3 Logger
*
* Note: This middleware should be added last. It will not handle any exceptions/errors
* for middleware added after it.
*/
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
// ...
$app->run();
您现在可以对任何类型的 Exception 或 Throwable 映射自定义处理程序。
<?php
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// Optional: Define custom error logger
$logger = new Logger('error');
$logger->pushHandler(new RotatingFileHandler('error.log'));
// Define Custom Error Handler
$customErrorHandler = function (
ServerRequestInterface $request,
Throwable $exception,
bool $displayErrorDetails,
bool $logErrors,
bool $logErrorDetails
) use ($app, $logger) {
if ($logger) {
$logger->error($exception->getMessage());
}
$payload = ['error' => $exception->getMessage()];
$response = $app->getResponseFactory()->createResponse();
$response->getBody()->write(
json_encode($payload, JSON_UNESCAPED_UNICODE)
);
return $response;
};
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger);
$errorMiddleware->setDefaultErrorHandler($customErrorHandler);
// ...
$app->run();
如果您想将自定义错误日志记录管道传输到 Slim 附带的默认 ErrorHandler
,则有两种方法可以做到这一点。
对于第一种方法,您可以简单地扩展 ErrorHandler
并存根 logError()
方法。
<?php
namespace MyApp\Handlers;
use Slim\Handlers\ErrorHandler;
class MyErrorHandler extends ErrorHandler
{
protected function logError(string $error): void
{
// Insert custom error logging function.
}
}
<?php
use MyApp\Handlers\MyErrorHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// Instantiate Your Custom Error Handler
$myErrorHandler = new MyErrorHandler($app->getCallableResolver(), $app->getResponseFactory());
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorMiddleware->setDefaultErrorHandler($myErrorHandler);
// ...
$app->run();
对于第二种方法,您可以提供符合 PSR-3 标准 的记录器,例如来自流行 Monolog 库的记录器。
<?php
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use MyApp\Handlers\MyErrorHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// Monolog Example
$logger = new Logger('app');
$streamHandler = new StreamHandler(__DIR__ . '/var/log', 100);
$logger->pushHandler($streamHandler);
// Add Error Middleware with Logger
$errorMiddleware = $app->addErrorMiddleware(true, true, true, $logger);
// ...
$app->run();
渲染已终于与处理脱钩。它仍会通过 ErrorRenderers
检测内容类型并适当地渲染内容。核心 ErrorHandler
扩展了已完全重构的 AbstractErrorHandler
类。默认情况下,它将调用受支持内容类型的适当 ErrorRenderer
。核心 ErrorHandler
为以下内容类型定义了渲染器
application/json
application/xml
和 text/xml
text/html
text/plain
对于任何内容类型,你可以注册自己的错误渲染器。因此,首先定义一个实现 \Slim\Interfaces\ErrorRendererInterface
的新错误渲染器。
<?php
use Slim\Interfaces\ErrorRendererInterface;
use Throwable;
class MyCustomErrorRenderer implements ErrorRendererInterface
{
public function __invoke(Throwable $exception, bool $displayErrorDetails): string
{
return 'My awesome format';
}
}
然后在核心错误处理程序中注册该错误渲染器。在下面的示例中,我们将注册该渲染器以用于 text/html
内容类型。
<?php
use MyApp\Handlers\MyErrorHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
// Get the default error handler and register my custom error renderer.
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', MyCustomErrorRenderer::class);
// ...
$app->run();
默认情况下,错误处理程序会尝试使用请求的 Accept
头检测错误渲染器。如果你需要强制错误处理程序使用特定的错误渲染器,可以编写以下内容。
$errorHandler->forceContentType('application/json');
我们在应用程序中添加了带名称的 HTTP 异常。这些异常与本机渲染器很好用。当调用本机 HTML 渲染器时,它们每个都可以有一个 description
和 title
属性,以提供更多详细信息。
基类 HttpSpecializedException
扩展 Exception
,并带有以下子类
如果你需要任何其他我们决定不使用基础存储库提供的响应代码,你可以扩展 HttpSpecializedException
类。例如,如果你希望出现 504 网关超时异常,并且其行为与本机异常类似,则应执行以下操作
class HttpGatewayTimeoutException extends HttpSpecializedException
{
protected $code = 504;
protected $message = 'Gateway Timeout.';
protected $title = '504 Gateway Timeout';
protected $description = 'Timed out before receiving response from the upstream server.';
}
要抛出 HTTP 异常,请使用以下代码
use Slim\Exception\HttpNotFoundException;
// ...
throw new HttpNotFoundException($request);
确保在抛出异常时传递 $request
对象。