文章彙整

Magento新增結帳步驟-Part 1

Astral WebBy Astral Web 2 years agoNo Comments
首頁  /  Magento  /  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-&gt;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-&gt;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,以及訂閱我們的電子報,隨時掌握最新新知分享唷!

 000

推薦文章

Categories:
  Magento後端開發網站技術與設計

留下回應

你的電子郵件地址不會被公開.