2010-10-19 8 views
6

Durante Zend_Controller_Action::init(), ¿hay alguna manera de cancelar la acción (por lo que no se llamará)?¿Puedo cancelar una acción Zend Controller en el método init()?

<?php 
class JsonApiController extends Zend_Controller_Action { 
    function init() 
    { 
     // try JSON decoding the raw request body 
     if ($jsonDecodingFailed) { 
      echo '{"error":"invalid JSON"}'; 
      $this->_cancelAction(); // something like this exist? 
     } 
    } 
} 

Mi solución actual es hacer un método vacío nullAction() y llame $this->_forward('null') remitir a la misma.

+0

¿Qué debería pasar cuando se cancela la solicitud? ¿Desea enviar encabezados específicos o renderizar una secuencia de comandos de vista? – Gordon

+0

Gordon, la vista/distribución está deshabilitada. Podría 'exit()', pero no quiero matar a todo el proceso de post-despacho. –

+0

pero ¿qué quieres devolver? Si no quieres simplemente 'salir', ¿qué debería pasar? Usted dice que está utilizando una solución, pero la pregunta es ¿para qué? ¿Qué hace nullAction? ¿Y por qué lo consideran una solución? En realidad, me cuesta entender cuál es tu pregunta o tu objetivo. – Gordon

Respuesta

2

No hay nada de malo en usar $ this -> _ forward() dentro de init() (si el método al que desea reenviar está dentro del mismo controlador que init()), esto simplemente cambiará el controlador del objeto de solicitud/acción (sobrescribe lo que se ha configurado a través del enrutador).

Una alternativa a esto sería crear un Zend_Controller_Plugin ya que parece que está manejando errores inesperados. Eche un vistazo a la implementación Zend_Controller_Plugin_ErrorHandler. Por lo tanto, en lugar de reenviar a otra acción, lanzaría una excepción y verificaría su plugin personalizado en postDispatch() si la respuesta contiene expectativas de eny, si simplemente edita el objeto de solicitud actual para mostrar su acción de "cancelar".

$request->setDispatched(false) 
     ->setControllerName("error") 
     ->setActionName("jsonDecoding"); 

La última forma podría ser simplemente tirar una salida después del eco "{Error: 'JSON válida'}" no es muy agradable, pero que evitará la sobrecarga de tener otra iteración de despacho.

+0

Gracias. Encontré que puedo usar 'setErrorHandler()' en el plugin ErrorHandler predeterminado para tener excepciones manejadas en el mismo controlador –

+1

Utilicé temporalmente 'exit()', pero además de no ser una solución muy buena, también hace que sea imposible escribir funcional pruebas porque las pruebas también se matarán en este punto (y me llevó un tiempo averiguar por qué las pruebas no arrojaron ningún resultado). Otra razón para evitar 'exit()'. – rkallensee

2

Yo lanzaría una excepción (y luego la vería en el controlador de error) - eso es lo que se hace cuando hay un error no recuperable.

0

De acuerdo con la documentation (en "Pre y Post-Dispatch ganchos"), llamando _forward() en preDispatch() se saltará la acción.

Específicamente sobre preDispatch(): "su objetivo principal es tomar decisiones sobre si se debe enviar o no la acción solicitada. De lo contrario, debe _forward() hacer otra acción o lanzar una excepción".

3

Tal vez intente esto:

$this->_helper->viewRenderer->setNoRender(); 
return; 
1

Para alguien que todavía está buscando solución puede probar esto: Añadir una bandera que indica si hay un error o no, y reemplazar el método de envío. Si la bandera está configurada, no invoque parent::dispatch.

Esto funciona como yo quiero. Mi razón fue que estoy creando un controlador API abstracto, que de forma predeterminada busca una clave API en la solicitud, si no está allí, el controlador debe responder con un error y completar la solicitud con éxito.

E.g.

abstract class Api_Controller extends Zend_Rest_Controller{ 
private $responded = false; 
public function init() { 
    parent::init(); 
    if(!$this->isKeyValid()) 
     $this->respond("invalid key"); // this would set flag to true and handle error 
} 
public function dispatch($action) { 
    // if an error occured and it was dispatched, do not call action method, just finish request 
    if(!$this->responded) 
     parent::dispatch($action); 
} 
} 

Para mí, esto parece una solución limpia.

+0

excelente :). Solo una pequeña corrección: $ this-> respondido ("clave inválida"); –

Cuestiones relacionadas