【问题标题】:CakePHP 3: Exception handling / serialization in a RESTful APICakePHP 3:RESTful API 中的异常处理/序列化
【发布时间】:2018-10-18 03:32:32
【问题描述】:

我正在使用 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 中更改异常的序列化行为?

【问题讨论】:

    标签: json cakephp exception-handling cakephp-3.0


    【解决方案1】:

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

    这是一个快速而肮脏的示例,使用名为 ValidationErrorException 的自定义异常(CakePHP 核心已使用 InternalErrorException),它扩展了 \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);
    }
    

    另见

    【讨论】:

    • 谢谢。我猜我必须使用自定义的 ExceptionRenderer,但我不确定如何构建输出消息。我还添加了 $response = $this->controller->getResponse()->withStatus($code);this->controller->setResponse($response); 以将 http 状态传递给输出。
    • 糟糕,我忘记了标题和状态代码,我已经更新了代码示例。 @chrisch
    • 谁发现了这个:这是来自 friendsofcake/crud 插件的更新版本:github.com/FriendsOfCake/crud/blob/master/src/Error/Exception/…(信用:@ADmad)
    猜你喜欢
    • 2013-10-11
    • 1970-01-01
    • 2020-08-15
    • 2020-09-18
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多