Magento新增結帳步驟-Part 1
在magento 增加一個結帳步驟不是一件容易的事情,需要了解templates和blocks的關係,以及javascript顯示和隱藏相關步驟。
首先,我們有六個步驟,login/register、billing information、shipping information、shipping method、payment information、order review。
每個checkout steps的Templates files如下
- Login/Register –
frontend/rwd/default/template/persistent/checkout/onepage/login.phtml
- Billing Information –
frontend/rwd/default/template/persistent/checkout/onepage/billing.phtml
- Shipping Information –
frontend/rwd/default/template/checkout/onepage/shipping.phtml
- Shipping Method –
frontend/base/default/template/checkout/onepage/shipping_method.phtml
- Payment Information –
frontend/rwd/default/template/checkout/onepage/payment.phtml
- Order Review –
frontend/base/default/template/checkout/onepage/review.phtml
這些Templates files都被包在一個Template file
frontend/rwd/default/template/checkout/onepage.phtml
讓我們看一下在checkout.xml裡面的templates,以及它們使用了哪些block type
<checkout_onepage_index> .... <reference name="content"> <block type="checkout/onepage" name="checkout.onepage" template="checkout/onepage.phtml"> <block type="checkout/onepage_login" name="checkout.onepage.login" as="login" template="checkout/onepage/login.phtml"> <block type="page/html_wrapper" name="checkout.onepage.login.before" as="login_before" translate="label"> <label>Login/Registration Before</label> <action method="setMayBeInvisible"><value>1</value></action> </block> </block> <block type="checkout/onepage_billing" name="checkout.onepage.billing" as="billing" template="checkout/onepage/billing.phtml"/> <block type="checkout/onepage_shipping" name="checkout.onepage.shipping" as="shipping" template="checkout/onepage/shipping.phtml"/> <block type="checkout/onepage_shipping_method" name="checkout.onepage.shipping_method" as="shipping_method" template="checkout/onepage/shipping_method.phtml"> <block type="checkout/onepage_shipping_method_available" name="checkout.onepage.shipping_method.available" as="available" template="checkout/onepage/shipping_method/available.phtml"/> <block type="checkout/onepage_shipping_method_additional" name="checkout.onepage.shipping_method.additional" as="additional" template="checkout/onepage/shipping_method/additional.phtml"/> </block> <block type="checkout/onepage_payment" name="checkout.onepage.payment" as="payment" template="checkout/onepage/payment.phtml"> <block type="checkout/onepage_payment_methods" name="checkout.payment.methods" as="methods" template="checkout/onepage/payment/info.phtml"> <action method="setMethodFormTemplate"><method>purchaseorder</method><template>payment/form/purchaseorder.phtml</template></action> </block> </block> <block type="checkout/onepage_review" name="checkout.onepage.review" as="review" template="checkout/onepage/review.phtml"/> </block> </reference> </checkout_onepage_index>
使用於結帳步驟的block type可以看到如下
- Checkout Wrapper
checkout/onepage
Mage/Checkout/Block/Onepage.php
- Login/Register
checkout/onepage_login
Mage/Checkout/Block/Onepage/Login.php
- Billing Information
checkout/onepage_billing
Mage/Checkout/Block/Onepage/Billing.php
- Shipping Information
checkout/onepage_shipping
Mage/Checkout/Block/Onepage/Shipping.php
- Shipping Method
checkout/onepage_shipping_method
Mage/Checkout/Block/Onepage/Shipping/Method.php
- Payment Information
checkout/onepage_payment
Mage/Checkout/Block/Onepage/Payment.php
- Order Review
checkout/onepage_review
Mage/Checkout/Block/Onepage/Review.php
使用於結帳步驟的Javascript被定義在 template file
app/design/frontend/rwd/default/template/checkout/onepage.phtml
<div class="page-title"> <h1><?php echo $this->__('Checkout') ?></h1> </div> <script type="text/javascript" src="<?php echo $this->getJsUrl('varien/accordion.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout_rwd.js') ?>"></script>
首先,讓我們看 Onepage.php,可以看 getSteps() method.
public function getSteps() { $steps = array(); $stepCodes = $this->_getStepCodes(); if ($this->isCustomerLoggedIn()) { $stepCodes = array_diff($stepCodes, array('login')); } foreach ($stepCodes as $step) { $steps[$step] = $this->getCheckout()->getStepData($step); } return $steps; }
如果我們再看看 Mage_Checkout_Block_Onepage_Abstract class 裡的 _getStepCodes() method
app/code/core/Mage/Checkout/Block/Onepage/Abstract.php
protected function _getStepCodes() { return array('login', 'billing', 'shipping', 'shipping_method', 'payment', 'review'); }
接下來,我們會看到magento如何初始化checkout steps,你也許也注意到有其他初始化checkout steps的地方
skin/frontend/base/default/js/opcheckout.js
var Checkout = Class.create(); Checkout.prototype = { initialize: function(accordion, urls){ this.accordion = accordion; this.progressUrl = urls.progress; this.reviewUrl = urls.review; this.saveMethodUrl = urls.saveMethod; this.failureUrl = urls.failure; this.billingForm = false; this.shippingForm= false; this.syncBillingShipping = false; this.method = ''; this.payment = ''; this.loadWaiting = false; this.steps = ['login', 'billing', 'shipping', 'shipping_method', 'payment', 'review']; //We use billing as beginning step since progress bar tracks from billing this.currentStep = 'billing'; this.accordion.sections.each(function(section) { Event.observe($(section).down('.step-title'), 'click', this._onSectionClick.bindAsEventListener(this)); }.bind(this)); this.accordion.disallowAccessToNextSections = true; },
所以現在我們已經看到magento checkout 的基本概念,讓我們新增一個顯示在Login/Register step之後以及Billing Step之前的checkout step。
Checkout steps 將會增加一個客製化的theme,讓我們開始定義自己的module。
app/etc/modules/Astral_Customcheckout.xml
<?xml version="1.0"?> <config> <modules> <Astral_Customcheckout> <codePool>local</codePool> <active>true</active> </Astral_Customcheckout> </modules> </config>
每個checkout step 有自己的block class,因此我們需要新增一個。
建立一個config.xml 以及增加一個標籤在<block>區塊裡。
app/code/local/Astral/Customcheckout/etc/config.xml
<?xml version="1.0"?> <config> <global> <blocks> <customcheckout> <class>Astral_Customcheckout_Block</class> </customcheckout> </blocks> </global> </config>
然後增加checkout step block
app/code/local/Astral/Customcheckout/Block/Checkout/Onepage/Customstep.php
<?php class Astral_Customcheckout_Block_Checkout_Onepage_Customstep extends Mage_Checkout_Block_Onepage_Abstract { protected function _construct() { $this->getCheckout()->setStepData('customstep', array( 'label' => Mage::helper('checkout')->__('Custom Step'), 'is_show' => $this->isShow() )); if ($this->isCustomerLoggedIn()) { $this->getCheckout()->setStepData('customstep', 'allow', true); $this->getCheckout()->setStepData('billing', 'allow', false); } parent::_construct(); } }
如前所述_getStepCodes()需要被覆蓋,為了新增的步驟被新增進array,因此我們需要在config.xml增加一個覆蓋的設定
app/code/local/Astral/Customcheckout/etc/config.xml
<?xml version="1.0"?> <config> <global> <blocks> <customcheckout> <class>Astral_Customcheckout_Block</class> </customcheckout> <checkout> <rewrite> <onepage>Astral_Customcheckout_Block_Checkout_Onepage</onepage> </rewrite> </checkout> </blocks> </global> </config>
app/code/local/Astral/Customcheckout/Block/Checkout/Onepage.php
<?php class Astral_Customcheckout_Block_Checkout_Onepage extends Mage_Checkout_Block_Onepage { public function getSteps() { $steps = array(); if (!$this->isCustomerLoggedIn()) { $steps['login'] = $this->getCheckout()->getStepData('login'); } // New code $stepCodes = array('customstep','billing', 'shipping', 'shipping_method', 'payment', 'review'); foreach ($stepCodes as $step) { $steps[$step] = $this->getCheckout()->getStepData($step); } return $steps; } public function getActiveStep() { // If the user is already logged in, go to the new 'customstep' step return $this->isCustomerLoggedIn() ? 'customstep' : 'login'; } }
Magento 在onepage.phtml裡面引入opcheckout.js,而不是透過layout XML,所以在onepage.phtml需要增加包含額外checkout step的javascript file。
我們可以在config.xml指定一個frontend layout xml
app/code/local/Astralweb/Customcheckout/etc/config.xml
<?xml version="1.0"?> <config> <global> <blocks> <customcheckout> <class>Astralweb_Customcheckout_Block</class> </customcheckout> <checkout> <rewrite> <onepage>Astralweb_Customcheckout_Block_Checkout_Onepage</onepage> </rewrite> </checkout> </blocks> </global> <frontend> <layout> <updates> <customcheckout> <file>customcheckout.xml</file> </customcheckout> </updates> </layout> </frontend> </config>
在customcheckout.xml layout file,覆蓋原生地template onepage.phtml 使用我們客製的 onepage.phtml以及包含額外checkout step 的template
app/design/frontend/Your_Package/your_theme/layout/customcheckout.xml
<?xml version="1.0"?> <layout> <checkout_onepage_index> <reference name="checkout.onepage"> <action method="setTemplate"> <template>customcheckout/onepage.phtml</template> </action> <block type="customcheckout/checkout_onepage_customstep" name="customstep" template="customcheckout/onepage/customstep.phtml" /> </reference> </checkout_onepage_index> </layout>
由於在checkout javascript 有一個checkout step的code,我們需要藉由增加custom javascript file 到 onepage.phtml去覆蓋它。
app/design/frontend/Your_Package/your_theme/template/customcheckout/onepage.phtml
<?php <div class="page-title"> <h1><?php echo $this->__('Checkout') ?></h1> </div> <script type="text/javascript" src="<?php echo $this->getJsUrl('varien/accordion.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout_rwd.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('customcheckout/js/customcheckout.js') ?>"></script> ....
在這個檔案裡,增加了新的checkout step code。
skin/frontend/Your_Package/your_theme/customcheckout/js/customcheckout.js
var Customcheckout = Class.create(Checkout, { initialize: function($super,accordion, urls){ $super(accordion, urls); // New checkout step added this.steps = ['login', 'customstep' ,'billing', 'shipping', 'shipping_method', 'payment', 'review']; }, setMethod: function(){ if ($('login:guest') && $('login:guest').checked) { this.method = 'guest'; var request = new Ajax.Request( this.saveMethodUrl, {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'guest'}} ); Element.hide('register-customer-password'); this.gotoSection('customstep'); } // else if($('login:register') && ($('login:register').checked || $('login:register').type == 'hidden')) { this.method = 'register'; var request = new Ajax.Request( this.saveMethodUrl, {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'register'}} ); Element.show('register-customer-password'); this.gotoSection('customstep'); } else{ alert(Translator.translate('Please choose to register or to checkout as a guest')); return false; } } });
在 onepage.phtml的底部,預設的Checkout class會被初始化,我們現在需要換成Customcheckout class
app/design/frontend/Your_Package/your_theme/template/customcheckout/onepage.phtml
<?php <div class="page-title"> <h1><?php echo $this->__('Checkout') ?></h1> </div> <script type="text/javascript" src="<?php echo $this->getJsUrl('varien/accordion.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('js/opcheckout_rwd.js') ?>"></script> <script type="text/javascript" src="<?php echo $this->getSkinUrl('customcheckout/js/customcheckout.js') ?>"></script> .... <script type="text/javascript"> //<![CDATA[ var accordion = new Accordion('checkoutSteps', '.step-title', true); <?php if($this->getActiveStep()): ?> accordion.openSection('opc-<?php echo $this->getActiveStep() ?>'); <?php endif ?> var checkout = new Customcheckout(accordion,{ progress: '<?php echo $this->getUrl('checkout/onepage/progress') ?>', review: '<?php echo $this->getUrl('checkout/onepage/review') ?>', saveMethod: '<?php echo $this->getUrl('checkout/onepage/saveMethod') ?>', failure: '<?php echo $this->getUrl('checkout/cart') ?>'} ); //]]> </script>
在我們指定的layout file,custom checkout step將被新增在customcheckout/onepage目錄,讓我們現在新增。
app/design/frontend/Your_Package/your_theme/template/customcheckout/onepage/customstep.phtml
<form id="customstep-form" action=""> <fieldset> <ul class="form-list"> <li id="customstep"> <fieldset> <ul> <li class="wide"> <label for="customstep"><?php echo $this->__('Welcome to your new step!') ?></label> </li> </ul> </fieldset> </li> </ul> <div class="buttons-set" id="customstep-buttons-container"> <button type="button" title="<?php echo $this->__('Continue') ?>" class="button" onclick="customstep.save()"><span><span><?php echo $this->__('Continue') ?></span></span></button> <span class="please-wait" id="customstep-please-wait" style="display:none;"> <img src="<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif') ?>" alt="<?php echo $this->__('Loading next step...') ?>" title="<?php echo $this->__('Loading next step...') ?>" class="v-middle" /> <?php echo $this->__('Loading next step...') ?> </span> </div> </fieldset> </form> <script type="text/javascript"> //<![CDATA[ var customstep = new CustomStep('customstep-form','<?php echo $this->getUrl('checkout/onepage/saveCustomStep') ?>'); var customstepForm = new VarienForm('customstep-form'); //]]> </script>
OK,到這步驟你已經可以在頁面上看到custom step的label以及continue button,但是還不能保存資料,在下一篇Magento新增結帳步驟-Part2中介紹如何保存資料。
以上為本次歐斯瑞針對Magento新增結帳步驟的教學分享,歡迎各位追蹤歐斯瑞臉書粉絲頁、Instagram,以及訂閱我們的電子報,隨時掌握最新新知分享唷!
我要留言