usar getdata como php ajax cakephp error-handling

getdata - como usar ajax en cakephp



Manejo de errores Ajax en CakePHP (3)

Quiero hacer algo muy similar a esto, pero en el mundo de CakePHP para las solicitudes de AJAX. Por el momento estoy haciendo esto:

$this->autoRender = false; $this->response->statusCode(500);

Está basado en esto . Sin embargo, esta solución no me permite incluir un mensaje personalizado, como en el ejemplo de Rails, para que de esa manera, en el controlador de errores del lado de mis clientes, pueda mostrar el mensaje incluido en la respuesta de error 500.

¿Cómo implementaría la misma funcionalidad en CakePHP como el ejemplo de Ruby on Rails?


Puede usar CakeExceptions como se explica en el Libro de cocina: http://book.cakephp.org/2.0/en/development/exceptions.html PERO, si desea usar sus mensajes personalizados, no encontré otra manera que usar debug = 1 en su modo de producción :(

Aquí está mi enfoque con métodos integrados:

En tu controlador:

if($this->request->is(''ajax'')){ Configure::write(''debug'', 1); } if(!$allowed) { throw new InternalErrorException(''Keep your fingers away from me!''); // 500 error }

Cambie la plantilla de error para que no /app/View/Errors/error500.ctp: nada más que el error cuando se utiliza en llamadas AJAX en /app/View/Errors/error500.ctp:

<?php if($this->request->is(''ajax'')): // Output for AJAX calls echo $name; else: //Standard CakePHP output ?> <h2><?php echo $name; ?></h2> <p class="error"> <strong><?php echo __d(''cake'', ''Error''); ?>: </strong> <?php echo __d(''cake'', ''An Internal Error Has Occurred.''); ?> </p> <?php if (Configure::read(''debug'') > 0 ): echo $this->element(''exception_stack_trace''); endif; endif; ?>

Luego puede analizar el texto devuelto en su AJAX. Aquí están las partes jQuery que uso:

//... error: function (request) { yourErrorShowingFunction(_this, request.responseText); } //...

Espero que esto ayude :)

Si alguien tiene una idea de cómo usar los errores personalizados en el modo de producción (sin sobreescribir el modo de depuración) ¡estaría muy feliz!


También he tenido problemas con las excepciones personalizadas y los códigos de error cuando uso las solicitudes ajax (jquery mobile en mi caso). Aquí está la solución que se me ocurrió, sin involucrar sobrescribir el modo de depuración. Lanza errores personalizados en el modo de desarrollo, y también opcionalmente en modo de producción. Espero que esto ayude a alguien:

AppExceptionRenderer.php:

<?php App::uses(''ExceptionRenderer'', ''Error''); class AppExceptionRenderer extends ExceptionRenderer { public function test($error) { $this->_sendAjaxError($error); } private function _sendAjaxError($error) { //only allow ajax requests and only send response if debug is on if ($this->controller->request->is(''ajax'') && Configure::read(''debug'') > 0) { $this->controller->response->statusCode(500); $response[''errorCode''] = $error->getCode(); $response[''errorMessage''] = $error->getMessage(); $this->controller->set(compact(''response'')); $this->controller->layout = false; $this->_outputMessage(''errorjson''); } } }

Puede omitir Configure::read(''debug'') > 0 si desea mostrar la excepción en modo de depuración. La vista errorjson.ctp se encuentra en ''Error / errorjson.ctp'':

<?php echo json_encode($response); ?>

En este caso mi excepción se llama

TestException

y se define de la siguiente manera:

<?php class TestException extends CakeException { protected $_messageTemplate = ''Seems that %s is missing.''; public function __construct($message = null, $code = 2) { if (empty($message)) { $message = ''My custom exception.''; } parent::__construct($message, $code); } }

Donde tengo un código de error personalizado 2, $code = 2 , para mi respuesta json. La respuesta ajax emitirá un error 500 con los siguientes datos de json:

{"errorCode":"2","errorMessage":"My custom exception."}

Obviamente, también necesita lanzar la excepción desde su controlador:

throw new TestException();

e incluir el procesador de excepciones http://book.cakephp.org/2.0/en/development/exceptions.html#using-a-custom-renderer-with-exception-renderer-to-handle-application-exceptions

Esto puede estar un poco fuera del alcance, pero para manejar la respuesta de error ajax en JQuery utilizo:

$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { //deal with my json error });


Como se mencionó anteriormente, las excepciones son la forma de devolver un error en una solicitud AJAX en CakePHP. Aquí está mi solución para obtener un control más preciso de cómo se ve el error. Además, como se indicó anteriormente, estoy usando un Renderizador de excepciones personalizado, pero no una excepción personalizada. La respuesta de error predeterminada es un objeto JSON como este:

{"name":"An Internal Error Has Occurred", "url": "//users//login.json"}

Casi me gusta la forma en que el renderizador predeterminado maneja los errores AJAX; Solo quiero modificarlo un poco:

<?php // File: /app/Lib/Error/CustomExceptionRenderer.php App::uses(''ExceptionRenderer'', ''Error''); class CustomExceptionRenderer extends ExceptionRenderer { // override public function error400($error) { $this->_prepareView($error, ''Not Found''); $this->controller->response->statusCode($error->getCode()); $this->_outputMessage(''error400''); } // override public function error500($error) { $this->_prepareView($error, ''An Internal Error Has Ocurred.''); $code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500; $this->controller->response->statusCode($code); $this->_outputMessage(''error500''); } private function _prepareView($error, $genericMessage) { $message = $error->getMessage(); if(!Configure::read(''debug'') && !Configure::read(''detailed_exceptions'')) { $message = __d(''cake'', $genericMessage); } $url = $this->controller->request->here(); $renderVars = array( ''name'' => h($message), ''url'' => h($url), ); if(isset($this->controller->viewVars[''csrf_token''])) { $renderVars[''csrf_token''] = $this->controller->viewVars[''csrf_token'']; } $renderVars[''_serialize''] = array_keys($renderVars); $this->controller->set($renderVars); } }

Luego, en bootstrap.php:

Configure::write(''Exception.renderer'', ''CustomExceptionRenderer'');

Pues así es como funciona:

  • Supongamos que quiero devolver un nuevo token CSRF en mi respuesta de error, de modo que si mi token existente ha caducado antes de que se lanzara la excepción, la próxima vez que intento la solicitud no me piratearán. Consulte la documentación del componente de seguridad para obtener más información sobre la protección CSRF.
  • Crea una nueva clase en la aplicación / Lib / Error. Puede extender el renderizador predeterminado, o no. Como solo quiero cambiar algunas cosas pequeñas, y para mantener el ejemplo simple, lo estoy extendiendo.
  • Anule los métodos que usa el procesador predeterminado para crear el objeto JSON que se devolverá. Esto se hace a través del Componente del Manejador de Solicitudes y se ajusta a las mejores prácticas. De hecho, el renderizador predeterminado hace lo mismo.
  • Nuevo método privado para mantener las cosas SECAS.
  • Mi solución al problema de no recibir mensajes de error personalizados en producción es agregar una clave de configuración opcional. De forma predeterminada, esta clase mostrará los mensajes genéricos en producción, pero si tiene la depuración establecida en 0, y desea los mensajes de error específicos: Configure::write(''detailed_exceptions'', 1);
  • Agregue el nuevo token a la respuesta si existe. En mi caso, ya he llamado a Controller::set en el nuevo token en el método beforeFilter de AppController, por lo que está disponible en $this->controller->viewVars . Probablemente haya docenas de otras formas de lograr esto.

Ahora su respuesta es así:

{ "name":"The request has been black-holed", "url":"//users//login.json", "csrf_token":"1279f22f9148b6ff30467abaa06d83491c38e940" }

Cualquier información adicional, de cualquier tipo, se puede agregar a la matriz pasada a Controller::set para obtener el mismo resultado.