在Magento Checkout Onepage 中SaveBilling处理大致可分以下几步
1、通过Ajax提交到OnePageController.php的saveBillingAction方法
//在billing.phtml中利用Javascript对Billing类进行创建,并在该页面中通过billing.save()来进行Ajax请求 var billing = new Billing('co-billing-form', '<?php echo $this->getUrl('checkout/onepage/getAddress') ?>address/', '<?php echo $this->getUrl('checkout/onepage/saveBilling') ?>'); //javascript'save方法 save: function(){ if (checkout.loadWaiting!=false) return; var validator = new Validation(this.form); if (validator.validate()) { if (checkout.method=='register' && $('billing:customer_password').value != $('billing:confirm_password').value) { alert(Translator.translate('Error: Passwords do not match')); return; } checkout.setLoadWaiting('billing'); // if ($('billing:use_for_shipping') && $('billing:use_for_shipping').checked) { // $('billing:use_for_shipping').value=1; // } var request = new Ajax.Request( this.saveUrl, { method: 'post', onComplete: this.onComplete, onSuccess: this.onSave, onFailure: checkout.ajaxFailure.bind(checkout), parameters: Form.serialize(this.form) } ); } }
2、处理saveBillingAction中saveBilling方法
$result = $this->getOnepage()->saveBilling($data, $customerAddressId);
2.1 分析sales_flat_quote_address表中有无addressid(一条billing信息就有一个addressid与之相对应),有则更新,无则追加
$address = $this->getQuote()->getBillingAddress(); if (!empty($customerAddressId)) { $customerAddress = Mage::getModel('customer/address')->load($customerAddressId); if ($customerAddress->getId()) { if ($customerAddress->getCustomerId() != $this->getQuote()->getCustomerId()) { return array('error' => 1, 'message' => Mage::helper('checkout')->__('Customer Address is not valid.') ); } $address->importCustomerAddress($customerAddress); } } else { unset($data['address_id']); $address->addData($data); //$address->setId(null); }
2.2$this->getQuote()->collectTotals();进行金额计算
展开这个方法,会发现这个方法是在 app/code/core/Mage/Sales/Model/Quote/Address.php中定义,其内用反射来找到当前需要计算的模块,而 collect函数则在app/code/core/Mage/Sales/Model/Quote/Address/Total/下(通过 getTotalModels可以看到其命名空间),也就是说,不管是shipping、subtotal、grand、handling fee、tax、discount等运算规则,其内的运算方法名是统一的,名为collect()。这也就是模板模式。
public function collectTotals() { foreach ($this->getTotalModels() as $model) { if (is_callable(array($model, 'collect'))) { $model->collect($this); } } return $this; }
3、根据用户是否选择the same as shipping information来决定执行_getShippingMethodsHtml
4、执行_getShippingMethodsHtml
返回layout中的checkout_onepage_shippingmethod 块信息(其内有显示available.phtml与additional.phtml的信息。具体请参见layout/checkout.xml下 block=”checkout_onepage_shippingmethod”下的附属块结点所对应模板的phtml文件)
protected function _getShippingMethodsHtml() { $layout = $this->getLayout(); $update = $layout->getUpdate(); $update->load('checkout_onepage_shippingmethod'); $layout->generateXml(); $layout->generateBlocks(); $output = $layout->getOutput(); return $output; }
5、将块信息进行json编码,返回给opcheckout.js的savebilling的ajax
$result['update_section'] = array( 'name' => 'shipping-method', 'html' => $this->_getShippingMethodsHtml() ); $this->getResponse()->setBody(Zend_Json::encode($result));
6、在opcheckout.js中 savebilling成功后调用onSave,而onSave指向的是nextstep函数
nextStep: function(transport){ if (transport && transport.responseText){ try{ response = eval('(' + transport.responseText + ')'); } catch (e) { response = {}; } } if (response.error){ if ((typeof response.message) == 'string') { alert(response.message); } else { if (window.billingRegionUpdater) { billingRegionUpdater.update(); } alert(response.message.join("/n")); } return false; } checkout.setStepResponse(response); } //而checkout.setStepResponse(response)为基类checkout的方法 setStepResponse: function(response){ if (response.update_section) { //response.update_section.html $('checkout-'+response.update_section.name+'-load').update(response.update_section.html); } //这里的response.update_section.html就是返回在服务器端返回的json,其格式如下{"update_section":{"html":"<div>...</div>"}}
其它模块类似。
本文转自 http://blog.csdn.net/liangpei2008/article/details/6084183
Comments on this entry are closed.