Magento中$this->getOrders()返回null的问题求助
getOrders()返回null的原因 嘿,我来帮你搞清楚这个问题!你遇到的核心误解是对Magento魔术方法的工作方式理解错了——它并不是在任意位置都能自动返回你需要的数据的,背后是有Block类的实现支撑的。
为什么原页面能正常运行?
原采购历史页面的模板(purchasehistory.phtml)是和特定的Block类绑定的,默认是Mage_Sales_Block_Order_History。这个Block类里已经专门实现了getOrders()方法:它会去查询当前登录用户的订单集合,处理筛选条件(比如只显示前端可见状态的订单),然后把这个集合返回给模板。所以模板里调用$this->getOrders()时,实际上是在调用这个Block类的方法,能拿到有效的订单集合,自然getSize()不会报错。
你的新页面为什么会报错?
你新建的PHP块如果只是简单创建了一个基础Block(比如继承Mage_Core_Block_Template),这个类里并没有实现getOrders()方法,也没有预先设置$_orders这个数据属性。Magento的魔术方法getXxx()的逻辑是:
- 先看Block类里有没有
getXxx()的显式方法,有就调用; - 如果没有,就尝试用
getData('xxx')获取对应的数据; - 如果两者都没有,就返回
null。
所以你的新Block里既没有getOrders()方法,也没设置orders数据,$this->getOrders()自然返回null,再调用getSize()就触发了“Call to a member function getSize() on null”的致命错误。
怎么解决这个问题?
有两种简单的方案:
方案一:继承原Block类
让你的新Block直接继承原采购历史的Block类,这样就能自动继承它的getOrders()方法和所有逻辑:class YourCustom_Module_Block_Purchasehistory extends Mage_Sales_Block_Order_History { // 如果不需要自定义逻辑,这里可以留空 }然后在CMS页面里调用这个自定义Block即可。
方案二:手动实现
getOrders()方法
如果需要自定义订单查询逻辑,就在你的新Block里自己写getOrders()方法,比如复制原Block的核心逻辑并修改:class YourCustom_Module_Block_Purchasehistory extends Mage_Core_Block_Template { public function getOrders() { if (!$this->hasData('orders')) { // 查询当前用户的订单集合 $orders = Mage::getResourceModel('sales/order_collection') ->addFieldToSelect('*') ->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getCustomerId()) // 只显示前端可见的订单状态 ->addFieldToFilter('state', array('in' => Mage::getSingleton('sales/order_config')->getVisibleOnFrontStates())) ->setOrder('created_at', 'desc'); $this->setData('orders', $orders); } return $this->getData('orders'); } }
总结一下
Magento里模板的$this对应的是当前绑定的Block实例,模板里的所有方法调用都依赖于这个Block类的实现。魔术方法只是简化了数据的获取,不能凭空生成你需要的业务数据——必须在Block里预先实现对应的方法或者设置好数据,模板才能正常调用。
内容的提问来源于stack exchange,提问作者sadeee nadeee

