#magento
#magento
Вопрос:
Я добавляю дополнительное поле флажка в Magento checkout для подписки на новостную рассылку с помощью нового модуля.
На данный момент я добавил код в свой файл макета (billing.phtml):
<p>Please untick this box if you do not wish to receive infrequent email updates and newsletters from us. <input type="checkbox" name="billing[is_subscribed]" title="" value="1" id="billing:is_subscribed" class="checkbox" checked="checked" /></p>
Я расширил класс ( app/code/local/Clientname/Checkout/Model/Type/Onepage.php
) — я расширил только метод savebilling:
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
* @package Mage_Checkout
* @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* One page checkout processing model
*/
class Eatyourwords_Checkout_Model_Type_Onepage extends Mage_Checkout_Model_Type_Onepage
{
public function saveBilling($data, $customerAddressId)
{
if (empty($data)) {
return array('error' => -1, 'message' => $this->_helper->__('Invalid data.'));
}
$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' => $this->_helper->__('Customer Address is not valid.')
);
}
$address->importCustomerAddress($customerAddress);
}
} else {
// process billing address and validate form
/* @var $addressForm Mage_Customer_Model_Form */
$addressForm = Mage::getModel('customer/form');
$addressForm->setFormCode('customer_address_edit')
->setEntity($address)
->setEntityType('customer_address')
->setIsAjaxRequest(Mage::app()->getRequest()->isAjax());
// emulate request object
$addressData = $addressForm->extractData($addressForm->prepareRequest($data));
$addressErrors = $addressForm->validateData($addressData);
if ($addressErrors !== true) {
return array('error' => 1, 'message' => $addressErrors);
}
$addressForm->compactData($addressData);
if (!empty($data['save_in_address_book'])) {
$address->setSaveInAddressBook(1);
}
}
// validate billing address
if (($validateRes = $address->validate()) !== true) {
return array('error' => 1, 'message' => $validateRes);
}
$address->implodeStreetAddress();
if (true !== ($result = $this->_validateCustomerData($data))) {
return $result;
}
if (!$this->getQuote()->getCustomerId() amp;amp; self::METHOD_REGISTER == $this->getQuote()->getCheckoutMethod()) {
if ($this->_customerEmailExists($address->getEmail(), Mage::app()->getWebsite()->getId())) {
return array('error' => 1, 'message' => $this->_customerEmailExistsMessage);
}
}
if (!$this->getQuote()->isVirtual()) {
/**
* Billing address using otions
*/
$usingCase = isset($data['use_for_shipping']) ? (int)$data['use_for_shipping'] : 0;
switch($usingCase) {
case 0:
$shipping = $this->getQuote()->getShippingAddress();
$shipping->setSameAsBilling(0);
break;
case 1:
$billing = clone $address;
$billing->unsAddressId()->unsAddressType();
$shipping = $this->getQuote()->getShippingAddress();
$shippingMethod = $shipping->getShippingMethod();
$shipping->addData($billing->getData())
->setSameAsBilling(1)
->setShippingMethod($shippingMethod)
->setCollectShippingRates(true);
$this->getCheckout()->setStepData('shipping', 'complete', true);
break;
}
}
$this->getQuote()->collectTotals();
if (isset($data['is_subscribed'])) {
$status = Mage::getModel(‘newsletter/subscriber’)->subscribe($data['email']);
}
$this->getQuote()->save();
$this->getCheckout()
->setStepData('billing', 'allow', true)
->setStepData('billing', 'complete', true)
->setStepData('shipping', 'allow', true);
return array();
}
}
В частности, в нижней части класса, который я вставил:
if (isset($data['is_subscribed'])) {
$status = Mage::getModel(‘newsletter/subscriber’)->subscribe($data['email']);
}
Я добавил файл, чтобы сообщить Magento об этом модуле ( app/etc/modules/Clientname_Checkout.xml
):
<?xml version="1.0"?>
<config>
<modules>
<Clientname_Checkout>
<active>true</active>
<codePool>local</codePool>
</Clientname_Checkout>
</modules>
</config>
Однако сейчас я застрял на последнем шаге того, как заставить Magento распознавать и использовать расширенный мной метод alernative save_billing. Я думаю, мне нужно добавить файл /app/code/local/Clientname/config.xml
.
Но я не понимаю, как я настроил это так, чтобы новый класс savebilling использовался вместо исходного.
Пожалуйста, кто-нибудь может помочь с этим последним шагом?
Спасибо
Саймон
Ответ №1:
Это хрестоматийный пример переопределения классов в Magento. Как вы, вероятно, знаете, Magento использует форму абстракции для загрузки классов на основе содержимого файлов конфигурации XML, расположенных по всей кодовой базе. Это означает, что мы можем загрузить модель Mage_Checkout_Model_Type_Onepage
путем вызова Mage::getModel('checkout/type_onepage')
с конфигурацией по умолчанию. Довольно интересной функцией является возможность изменять сопоставление ссылки на модель checkout/type_onepage
с фактическим именем класса.
Структура каталогов
Итак, вы проделали тяжелую работу: отредактировали шаблон и изменили метод model. Далее вам нужно создать небольшой модуль для выполнения перезаписи класса. На основе имени вашего класса вам понадобится структура каталогов вида:
/app
/etc
/modules
/Eatyourwords_Checkout.xml
/code
/local
/Eatyourwords
/Checkout
/etc
/config.xml
/Model
/Type
/Onepage.php
Выполнение перезаписи
Перезапись обрабатывается в файле конфигурации вашего модуля, config.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<eyw_c>
<version>1.0</version>
</eyw_c>
</modules>
<global>
<models>
<eyw_c>Eatyourwords_Checkout_Model</eyw_c>
<checkout>
<rewrite>
<type_onepage>Eatyourwords_Checkout_Model_Type_Onepage</type_onepage>
</rewrite>
</checkout>
</models>
</global>
</config>
Материал в <modules />
группе тегов — это всего лишь стандартная начальная загрузка для модуля.
В <models />
разделе мы определяем пространство имен, которое будет использоваться при загрузке любого из наших классов моделей. Так же, как checkout/type_onepage
, мы можем получить доступ к любым моделям, которые у нас есть в нашем /Model
каталоге, путем добавления eyw_c/*
.
Затем мы открываем Mage_Checkout
пространство имен model, <checkout />
и выполняем перезапись checkout/type_onepage
класса. Теперь, когда Magento пытается загрузиться checkout/type_onepage
, он будет искать наш класс. Все остальные checkout/*
классы не будут затронуты. Имя класса для них будет сконструировано обычным способом.
Включите модуль
Далее нам нужно указать Magento на новый модуль, который мы создали. Ваша попытка была почти правильной. Вы должны вызвать его Eatyourwords_Checkout.xml
и поместить в /app/etc/modules
:
<?xml version="1.0"?>
<config>
<modules>
<Eatyourwords_Checkout>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Checkout />
</depends>
</Eatyourwords_Checkout>
</modules>
</config>
.. и это сделано. Класс переопределен.
Комментарии:
1. Я думаю, что это работает и запуск переопределенного класса — хотя мой код не работает для подписки на электронную почту, так что, возможно, я ошибаюсь — нужно отладить!
2. @simonyoung: Извините, я не проверяю эту часть! Возможно, вам потребуется вызвать
->save()
модель, чтобы сбросить ее в базу данных.