【发布时间】:2011-06-11 09:28:16
【问题描述】:
我在事件 checkout_controller_onepage_save_shipping_method 期间验证运输报价,如果验证失败,我想将用户发送回运输方式选择,但我还想显示一条消息,说明失败的原因。 Magento 有内置的方法吗?
我已经在验证数据,只是缺少对运输方式的重定向和显示消息的方式。
【问题讨论】:
我在事件 checkout_controller_onepage_save_shipping_method 期间验证运输报价,如果验证失败,我想将用户发送回运输方式选择,但我还想显示一条消息,说明失败的原因。 Magento 有内置的方法吗?
我已经在验证数据,只是缺少对运输方式的重定向和显示消息的方式。
【问题讨论】:
(这些都不是经过测试的代码,但这些概念应该可以让你到达你需要去的地方)
Magento 是由一群软件工程师运行的项目。当您与一群软件工程师一起工作时,文档就是代码。
即每当您需要做一些与 Magento 共同的事情时,请观察核心团队是如何做到的,考虑到您应该将自己限制为观察者、覆盖和新代码,因为您无法与核心团队讨论您的更改。
看看单页结账控制器的IndexAction方法
app/code/core/Mage/Checkout/controllers/OnepageController.php
public function indexAction()
{
if (!Mage::helper('checkout')->canOnepageCheckout()) {
Mage::getSingleton('checkout/session')->addError($this->__('The onepage checkout is disabled.'));
$this->_redirect('checkout/cart');
return;
}
...
Magento 允许您向会话对象添加错误,这些错误将在下一个请求时由消息块处理。
Mage::getSingleton('checkout/session')->addError($this->__('The onepage checkout is disabled.'));
处理错误的那个。接下来是重定向。这发生在这里
$this->_redirect('checkout/cart');
由于您是从观察者调用此代码,因此您将无权访问此方法。但是,如果您检查控制器
/**
* Retrieve request object
*
* @return Mage_Core_Controller_Request_Http
*/
public function getRequest()
{
return $this->_request;
}
...
protected function _redirect($path, $arguments=array())
{
$this->getResponse()->setRedirect(Mage::getUrl($path, $arguments));
return $this;
}
你可以看到它使用响应对象。 Magento 使用全局响应对象(类似于 Zend 和其他 Web 框架)来处理发送回浏览器的内容(即重定向标头)。您可以通过
获得对同一对象的引用Mage::app()->getResponse()
并且可以使用类似的东西执行重定向
Mage::app()->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
【讨论】:
Mage::app()->getResponse()->setRedirct(Mage::getUrl('checkout/cart')); 应该是 Mage::app()->getResponse()->setRedirect(Mage::getUrl('checkout/cart')); 我会编辑,但它少于 6 个字符。谢谢艾伦!
为此我想出了一种不同的方法,而不必覆盖控制器。基本上我做同样的事情,但只是在观察者方法中。所以我也使用 checkout_controller_onepage_save_shipping_method 来验证运输方式,如果出现错误,我会将该错误添加到如下所示的会话变量中
$error = array('error' => -1, 'message' => Mage::helper('core')->__("Message here"));
Mage::getSingleton('checkout/session')->setSavedMethodError($error);
然后你可以为每个动作应用另一个观察者'controller_action_postdispatch_'.$this->getFullActionName()
所以我用它来观察 controller_action_postdispatch_checkout_onepage_saveShippingMethod 在那里我检查会话错误变量并设置响应正文(如果存在)。
$error = Mage::getSingleton('checkout/session')->getSavedMethodError();
if($error){
Mage::app()->getResponse()->setBody(Mage::helper('core')->jsonEncode($error));
}
Mage::getSingleton('checkout/session')->setSavedMethodError(false);
我不确定这是好是坏,所以请留下任何 cmets,但我知道我希望能够做到这一点而无需对课程进行任何重写。
这是有效的,因为您正在覆盖在 saveShippingMethod 操作中设置的响应正文。
【讨论】:
Alan Storm 的回答一如既往,内容丰富且富有启发性。但在这种情况下,单页结帐主要是 AJAX,它会忽略会话错误消息,直到离开结帐页面后您才会看到它。
在saveShippingMethodAction 中有以下行:
$result = $this->getOnepage()->saveShippingMethod($data);
...然后 $result 是 JSON 编码的。如果您覆盖 Mage_Checkout_Model_Type_Onepage::saveShippingMethod 来执行检查,然后控制返回的内容,您可以插入一条错误消息,该消息将返回给浏览器并在弹出窗口中显示给用户。
您的覆盖可能如下所示:
public function saveShippingMethod($shippingMethod)
{
if ($this->doesntApplyHere()) {
return array('error' => -1, 'message' => $this->_helper->__('Explain the problem here.'));
}
return parent::saveShippingMethod($shippingMethod);
}
【讨论】: