2012-11-06 22 views
10

Mam problem z wiadomościami magento. Buduję moduł niestandardowy, który teoretycznie powinien być w stanie ograniczyć dostęp do niektórych części sklepu. Stworzyłem obserwatora, który łączy się ze zdarzeniem controller_action_predispatch i sprawdza, czy użytkownik może uzyskać dostęp do bieżącego żądania. Jeśli akcja nie jest dostępna, obserwator przekierowuje użytkownika i ustawia informacje o błędzie. Chcę ustawić adres URL przekierowania na stronę, z której pochodzi klient, aby uniknąć kliknięcia w cały sklep. Patrzę na HTTP_REFERER i używam go, jeśli jest ustawiony, w przeciwnym razie przekierowuję klienta na stronę główną. Problem polega na tym, że w późniejszym przypadku (przekierowanie na stronie głównej) wszystko działa świetnie, ale gdy ustawiam adres URL na podstawie odnośnika, nie widzę komunikatu o błędzie w oknie komunikatu.Magento traci wiadomości po przekierowaniu

Kod od obserwatora ($name zmienna jest ciągiem znaków):

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); 

Co znalazłem interesujące jest, że jeśli będę robić żadnych zmian w pliku obserwatora i zapisać go, a następnie kolejna prośba, która kończy się niepowodzeniem i zostanie przekierowany do adresu URL odsyłacza, pokazuje informacje o błędzie, ale każdy kolejny traci wiadomości.

Myślałam, że problem jest w pełny adres URL i mój lokalny instalacyjne (używam domeny .local), ale tak próbowałem dodając

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

ale to nie pomogło.

Próbowałem również przekierowania za pomocą funkcji php header(), ale bez żadnego wyniku.

Cała pamięć podręczna jest wyłączona. Workflow, która wywołuje problem jest następujący:

  1. Idę do każdej dostępnej strony (na przykład/klienta/konta)
  2. Kliknij na odnośnik koszyka (koszyk na tym koncie jest wyłączona)
  3. Powrót do/klienta/konta i wyświetlany jest komunikat o błędzie
  4. Kliknij koszyka linku ponownie
  5. Powrót do/klienta/konta, ale bez komunikatu o błędzie

Każda wskazówka, gdzie szukać, zostanie doceniona.

+0

Czy możesz dezaktywować wszystkie swoje pamięci podręczne (+ FPC, jeśli Magento EE), aby sprawdzić, czy jest to problem z pamięcią podręczną? A propos, nie zrozumiałem wszystkich twoich wyjaśnień, zrozumiałeś, że komunikaty o błędach sesji są usuwane po pierwszym wyświetleniu? –

+0

Rozszerzyłem opis, mam nadzieję, że teraz jest jasne. – Zefiryn

Odpowiedz

4

Wiadomości zgubić ponieważ używasz niekorzystnego sposobu przekierowania w controller_action_predispatch. Twoje rozwiązanie powoduje z jednej strony "utratę wiadomości", z drugiej strony powoduje marnowanie mocy obliczeniowej serwera.

Kiedy spojrzysz na Mage_Core_Controller_Varien_Action::dispatch(), zobaczysz, że twoje rozwiązanie nie zatrzymuje wykonania bieżącej akcji, ale powinno to zrobić z przekierowaniem. Zamiast tego Magento wykonuje bieżącą akcję do końca, włączając w to renderowanie wiadomości, którą dodałeś wcześniej. Nic więc dziwnego, że wiadomość zgubiła się przy następnej próbie klienta, Magento już ją wcześniej renderował, z odpowiedzią serwera, która zawiera twoje przekierowanie.

Co więcej, zobaczysz w Mage_Core_Controller_Varien_Action::dispatch() tylko jedną możliwość zatrzymania wykonywania bieżącej akcji i przejdź bezpośrednio do przekierowania, które jest w linii 428 catch (Mage_Core_Controller_Varien_Exception $e) [...]. Więc musisz użyć Mage_Core_Controller_Varien_Exception, który jest dość niepopularny, ale jest jedynym właściwym rozwiązaniem dla twojego celu. Jedynym problemem jest to, że ta klasa ma błąd, ponieważ została wprowadzona w Magento 1.3.2. Ale można to łatwo naprawić.

Wystarczy stworzyć własną klasę, która pochodzi z 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; 
    } 
} 

Więc można obecnie realizować swoje rozwiązanie naprawdę czysta, że:

/** 
* 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); 

Będzie to działać w kontrolerze, ale jeśli próbujesz przekierować po wyjściowy został już wysłany, to można zrobić tylko poprzez javascript:

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

Dzięki, session_write_close(); załatwiłem sprawę dla mnie. –

+0

+1 dla session_write_close(), utknął na zawsze! dzięki –

0

to będzie działać, więc spróbuj go:

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

Oznacza to, że nie pozwalają ponownie wykonywać niczego innego.

Powiązane problemy