CakePHP 3:RESTful API 中的异常处理/序列化

2024-01-10

我正在使用 CakePHP3 构建 JSON RESTful API,但我不确定处理错误并向客户端提供有关错误的信息的最佳方法是什么。到目前为止,我的方法是,如果(例如)由于验证错误而保存实体失败,则抛出 HttpException。

在我的控制器中,我有以下内容:

if (!$this->Categories->save($categoryEntity)) {
    throw new InternalErrorException('Saving failed');
}

$this->set('status', 'Everything fine!');
$this->set('_serialize', true);

如果保存失败,异常会序列化为 json,响应如下所示:

{
 "message": "Saving failed",
 "url": "\/categories\/edit",
 "code": 500,
}

现在我想包含一些有关该错误的更详细信息。例如这样的事情:

{
 "message": "Saving failed",
 "errors":  "Validation error: Field id has to be numeric"
 "url": "\/categories\/edit",
 "code": 500,
}

我已经使用扩展的 HttpException 进行了尝试,该扩展将错误作为额外参数,但该额外参数未序列化。如何在异常中包含一些额外的信息或者如何更改 CakePHP3 中异常的序列化行为?


异常的序列化视图变量是硬编码在异常渲染器中的,您必须创建一个自定义/扩展变量来处理自定义异常,以便它可以获取它提供的附加数据。

这是一个快速而肮脏的示例,使用名为的自定义异常ValidationErrorException (InternalErrorException已被 CakePHP 核心使用),它扩展了\Cake\Http\Exception\HttpException,并实现了getValidationErrors()返回验证错误的方法:

// in src/Error/Exception/ValidationErrorException.php

namespace App\Error\Exception;

use Cake\Datasource\EntityInterface;
use Cake\Http\Exception\HttpException;

class ValidationErrorException extends HttpException
{
    protected $_validationErrors;

    public function __construct(EntityInterface $entity, $message = null, $code = 422)
    {
        $this->_validationErrors = $entity->getErrors();

        if ($message === null) {
            $message = 'A validation error occurred.';
        }

        parent::__construct($message, $code);
    }

    public function getValidationErrors()
    {
        return $this->_validationErrors;
    }
}

这样的 HTTP 异常将映射到具有匹配名称的异常呈现器类方法:

// in src/Error/AppExceptionRenderer.php

namespace App\Error;

use App\Error\Exception\ValidationErrorException;
use Cake\Error\ExceptionRenderer;

class AppExceptionRenderer extends ExceptionRenderer
{
    // HttpExceptions automatically map to methods matching the inflected variable name
    public function validationError(ValidationErrorException $exception)
    {
        $code = $this->_code($exception);
        $method = $this->_method($exception);
        $template = $this->_template($exception, $method, $code);

        $message = $this->_message($exception, $code);
        $url = $this->controller->request->getRequestTarget();

        $response = $this->controller->getResponse();
        foreach ((array)$exception->responseHeader() as $key => $value) {
            $response = $response->withHeader($key, $value);
        }
        $this->controller->setResponse($response->withStatus($code));

        $viewVars = [
            'message' => $message,
            'url' => h($url),
            'error' => $exception,
            'code' => $code,
            // set the errors as a view variable
            'errors' => $exception->getValidationErrors(),
            '_serialize' => [
                'message',
                'url',
                'code',
                'errors' // mark the variable as to be serialized
            ]
        ];
        $this->controller->set($viewVars);

        return $this->_outputMessage($template);
    }
}

在你的控制器中,你可以像这样抛出它,向它提供验证失败的实体:

if (!$this->Categories->save($categoryEntity)) {
    throw new \App\Error\Exception\ValidationErrorException($categoryEntity);
}

See also

  • Cookbook > 错误和异常处理 > 更改异常渲染器 https://book.cakephp.org/3.0/en/development/errors.html#change-the-exceptionrenderer
  • 源 > \Cake\Error\ExceptionRenderer::render() https://github.com/cakephp/cakephp/blob/3.6.2/src/Error/ExceptionRenderer.php#L155
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CakePHP 3:RESTful API 中的异常处理/序列化 的相关文章

随机推荐