2012-11-06 12 views
10

Ho un problema con i messaggi Magento. Sto costruendo un modulo personalizzato che in teoria dovrebbe essere in grado di limitare l'accesso ad alcune parti del negozio. Ho creato un osservatore che si aggancia all'evento controller_action_predispatch e verifica se l'utente può accedere alla richiesta corrente. Se non è possibile accedere all'azione, l'osservatore reindirizza l'utente e imposta le informazioni sull'errore. Voglio impostare l'url di reindirizzamento sulla pagina di provenienza del cliente per evitare di fare clic sull'intero negozio. Sto guardando il HTTP_REFERER e lo uso se è impostato, altrimenti reindirizzare il cliente alla home page. Il problema è che nel caso successivo (reindirizzamento della home page) tutto funziona alla grande ma quando imposto l'url in base al referente non vedo il messaggio di errore nella finestra del messaggio.Magento che perde i messaggi dopo il reindirizzamento

Il codice dall'osservatore ($name variabile è una stringa):

Mage::getSingleton('core/session')->addError('Acces to '.$name.' section is denied'); 
$url = Mage::helper('core/http')->getHttpReferer() ? Mage::helper('core/http')->getHttpReferer() : Mage::getUrl(); 
Mage::app()->getResponse()->setRedirect($url); 

Quello che ho trovato interessante è che se lo faccio alcun cambiamento nel file di osservatore e salvarlo, quindi la richiesta successiva, che non riesce e viene reindirizzato all'URL di referer mostra l'informazione di errore ma ogni successivo perde i messaggi.

Stavo pensando che il problema è nel pieno URL e il mio instalation locale (sto usando dominio .local), ma così ho provato ad aggiungere

$url = str_replace(Mage::getBaseUrl(), '/', $url); 

ma questo non ha aiutato.

Ho anche provato il reindirizzamento utilizzando la funzione php header() senza alcun risultato.

Tutta la cache è disabilitata. Il flusso di lavoro che fa scattare il problema è il seguente:

  1. ho intenzione di qualsiasi pagina accessibile (ad esempio/cliente/account)
  2. Clicca sul carrello di collegamento (spesa per questo account è disabilitata)
  3. Ritorna al/cliente/account e il messaggio di errore viene visualizzato
  4. Clicca sul carrello collegamento di nuovo
  5. Ritorna a/cliente/conto, ma nessun messaggio di errore

Qualsiasi suggerimento su dove guardare sarà apprezzato.

+0

Puoi disattivare tutte le cache (+ FPC se EE magento) per vedere se si tratta di un problema di cache? A proposito, non ho capito tutte le tue spiegazioni, hai capito che i messaggi di errore della sessione vengono cancellati dopo la prima visualizzazione? –

+0

Ho ampliato la descrizione, spero che ora sia chiaro. – Zefiryn

risposta

4

I messaggi si perdono a causa si utilizza un modo sfavorevole per un reindirizzamento in controller_action_predispatch. La tua soluzione causa da un lato il "messaggio perso" e dall'altro, spreca la potenza di elaborazione del tuo server.

Quando date un'occhiata a Mage_Core_Controller_Varien_Action::dispatch(), vedrete che la vostra soluzione non ferma l'esecuzione dell'azione corrente, ma dovrebbe farlo con un reindirizzamento. Invece Magento esegue l'azione corrente fino alla fine, incluso il rendering del messaggio che hai aggiunto prima. Quindi non c'è da stupirsi del perché il messaggio venga perso con la successiva richiesta del client, Magento lo ha già reso in precedenza, con la risposta del server che include il reindirizzamento.

Inoltre vedrete in Mage_Core_Controller_Varien_Action::dispatch() solo una possibilità per interrompere l'esecuzione dell'azione corrente e saltare direttamente al reindirizzamento, che è nella riga 428 catch (Mage_Core_Controller_Varien_Exception $e) [...]. Quindi devi usare Mage_Core_Controller_Varien_Exception che è piuttosto impopolare, ma l'unica soluzione giusta per il tuo scopo. L'unico problema è che questa classe ha un bug da quando è stato introdotto in Magento 1.3.2. Ma questo può essere facilmente risolto.

Basta creare una classe che deriva da Mage_Core_Controller_Varien_Exception:

/** 
* Controller exception that can fork different actions, 
* cause forward or redirect 
*/ 
class Your_Module_Controller_Varien_Exception 
    extends Mage_Core_Controller_Varien_Exception 
{ 
    /** 
    * Bugfix 
    * 
    * @see Mage_Core_Controller_Varien_Exception::prepareRedirect() 
    */ 
    public function prepareRedirect($path, $arguments = array()) 
    { 
     $this->_resultCallback = self::RESULT_REDIRECT; 
     $this->_resultCallbackParams = array($path, $arguments); 
     return $this; 
    } 
} 

Così ora è possibile implementare la soluzione davvero pulito con quello:

/** 
* Your observer 
*/ 
class Your_Module_Model_Observer 
{ 
    /** 
    * Called before frontend action dispatch 
    * (controller_action_predispatch) 
    * 
    * @param Varien_Event_Observer $observer 
    */ 
    public function onFrontendActionDispatch($observer) 
    { 
     // [...] 

     /* @var $action Mage_Core_Model_Session */ 
     $session = Mage::getSingleton('core/session'); 
     /* @var $helper Mage_Core_Helper_Http */ 
     $helper = Mage::helper('core/http'); 
     // puts your message in the session 
     $session->addError('Your message'); 
     // prepares the redirect url 
     $params = array(); 
     $params['_direct'] = $helper->getHttpReferer() 
      ? $helper->getHttpReferer() : Mage::getHomeUrl(); 
     // force the redirect 
     $exception = new Your_Module_Controller_Varien_Exception(); 
     $exception->prepareRedirect('', $params); 
     throw $exception; 
    } 
} 
24
//A Success Message 
Mage::getSingleton('core/session')->addSuccess("Some success message"); 

//A Error Message 
Mage::getSingleton('core/session')->addError("Some error message"); 

//A Info Message (See link below) 
Mage::getSingleton('core/session')->addNotice("This is just a FYI message..."); 

//These lines are required to get it to work 
session_write_close(); //THIS LINE IS VERY IMPORTANT! 
$this->_redirect('module/controller/action'); 

// or 
$url = 'path/to/your/page'; 
$this->_redirectUrl($url); 

Ciò funzionerà in un controllore, ma se si sta cercando di reindirizzare dopo l'uscita è già stata inviata, allora si può fare solo che, attraverso javascript:

<script language=”javascript” type=”text/javascript”> 
window.location.href=”module/controller/action/getparam1/value1/etc"; 
</script>  
+7

Grazie, session_write_close(); ha fatto il trucco per me. –

+0

+1 per session_write_close(), è rimasto bloccato per sempre! grazie –

0

questo funzionerà, in modo da provare:

$url = 'path/to/your/page'; 
$this->_redirectUrl($url); 
return false; 

Ciò significa che non si consente nuovamente di eseguire altro.

Problemi correlati