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,以及訂閱我們的電子報,隨時掌握最新新知分享唷!
我要留言