Establecer el mensaje de error una vez por solicitud de página
-
16-10-2019 - |
Pregunta
Estoy tratando de crear un módulo mínimo de pago total que evitará que alguien consulte con un total de menos que una cantidad configurable.
Estoy usando el evento sales_quote_save_before
Para mostrar un error en la página de pago/carrito cuando se abre.
<?xml version="1.0"?>
<config>
<frontend>
<events>
<sales_quote_save_before>
<observers>
<b2b>
<class>b2b/observer</class>
<method>checkTotalsCart</method>
</b2b>
</observers>
</sales_quote_save_before>
</events>
</frontend>
</config>
Y en el observador
public function checkTotalsCart()
{
if ($this->_hasCartError()) { /* does some checks, returns bool */
$this->_setErrorMessage();
}
}
protected function _setErrorMessage()
{
$session = Mage::getSingleton("b2b/session"); /* extends Mage_Core_Model_Session */
$session->addError($this->helper->getErrorMessage());
}
El problema es que cuando actualiza el carrito de la página del carrito, el mensaje de error aparece dos veces. Supongo que ese evento está sucediendo varias veces.
Intenté verificar si el mensaje se estableció previamente con una variable de sesión personalizada.
protected function _setErrorMessage()
{
$session = Mage::getSingleton("b2b/session");
if ($session->isErrorMessageAdded()) {
return;
}
$session->addError($this->helper->getErrorMessage());
$session->isErrorMessageAdded(true);
}
Pero eso tampoco funcionó. ¿Cómo puedo asegurarme de que un mensaje de error solo aparezca una vez por solicitud de página?
Archivos de módulo relevantes
Solución
Tu pensamiento era sólido, pero tu comprensión de los métodos mágicos de Magento es un poco inestable. los hasX
No es un setter, solo verifica la presencia de una propiedad de datos. Entonces te gustaría cambiar
$session->hasErrorMessage(true);
a
$session->setErrorMessage(true);
También si b2b/session
es un objeto de sesión real (es decir, persiste las cosas para la sesión de PHP para la recuperación posterior) sería desconfiado de usarlo para algo como esto. Si persiste accidentalmente la propiedad 'Error_message` en la sesión, lo que significa que el usuario solo verá este mensaje de error una vez por sección, cuando (aparece) su deseo es hacer que lo vean una vez por intentos de orden no válidos.
Por lo general, prefiero una variable de clase PHP estática para algo como esto
static protected $_hasErrorMessage=false;
protected function _setErrorMessage()
{
$session = Mage::getSingleton("b2b/session");
if (self::$_hasErrorMessage) {
return;
}
$session->addError($this->helper->getErrorMessage());
self::$_hasErrorMessage = true;
}
Otros consejos
Vamos a explorar addError
un momento. addError
es un método de conveniencia para no tener que hacer llamadas de mensaje de error como así:
Mage::getModel('core/message_collection')->add(Mage::getSingleton('core/message')->error($message));
Como puede ver, eso es realmente desordenado.
La mayoría de las implementaciones de addError
, incluido eso en Mage_core_model_session_abstract, tener un método llamado addMessage
, que esencialmente hacen lo que se enumera anteriormente. Utiliza un método local llamado getMessages
que implementa el patrón de recopilación de mensajes ya descrito. Vea abajo:
public function getMessages($clear=false)
{
//....stuff
if ($clear) {
$messages = clone $this->getData('messages');
$this->getData('messages')->clear();
Mage::dispatchEvent('core_session_abstract_clear_messages');
return $messages;
}
//...stuff
}
Entonces, ¿cómo te ayuda esto?
Podrías proporcionar el addMessage
Método en su propio modelo B2B/Sesión para pasar condicionalmente true
a getMessages
Para borrarlo, mostrando efectivamente solo el último conjunto de mensajes:
public function addMessage(Mage_Core_Model_Message_Abstract $message, $clear=false)
{
$this->getMessages($clear)->add($message);
Mage::dispatchEvent('core_session_abstract_add_message');
return $this;
}
Una solución que he usado (pensé que no es demasiado bonita) es recorrer los mensajes para la sesión y ver si esa cadena ya existe
/**
* @var Mage_Checkout_Model_Session $_checkout
*/
protected $_checkout;
protected function _addMessage($message)
{
$messages = array_values((array)$this->_checkout->getMessages());
foreach ($messages[0] as $existingMessages) {
foreach($existingMessages as $existingMessage) {
$existingMessage = array_values((array)$existingMessage);
if ($existingMessage[1] == $message) {
// If the message is already set, stop here
return;
}
}
}
// Add this message to the session/checkout
$this->_checkout->addError($message);
}