需求:
在shopping cart页面 每一个Item 前增加checkobx控件,
让购买者可以选中需要购买的物品。
然后点击购买按钮执行购买流程。
再完成购买或者回到上一页按钮的时候恢复原本的item到购物车内。
解决思路:利用临时表存储未选中的item数据。
在完成结算或者取消结算的时候从临时表中恢复数据到正式表。
解剖一下相关表结构
magento 关于cart item的表有两个:`sales_flat_quote_item`,`sales_flat_quote_item_option`
这两个表前一个的主见是后一个的外键 item_id 。
为了完成需求我们可以创建两个零时表,针对上面两个表,
另外还要在sales_flat_quote_item中添加一个是否被选中的标记,这些数据库操作通过升级脚本实现:
定义升级脚本集成的类:写在<global>下
<resources> <bysoft_mycheckout_setup> <setup> <module>Bysoft_Mycheckout</module> <class>Mage_Sales_Model_Mysql4_Setup</class> </setup> </bysoft_mycheckout_setup> </resources>
增加是否选中状态字段
<?php
$installer = $this;
$installer->startSetup();
$installer->addAttribute(
'quote_item',
'selected_item',
array(
'type' => 'int',
'grid' => false
)
);
$installer->endSetup();
增加临时表:
<?php
$installer = $this;
$installer->startSetup();
$installer->run("
create table `bysoft_sales_flat_quote_item` like sales_flat_quote_item;
create table `bysoft_sales_flat_quote_item_option` like sales_flat_quote_item_option;
");
$installer->endSetup();
点击确认选中的item的ajax方法
checkbox 控件:
<input <?php if ($_item->getData('selected_item')):?>checked="checked"<?php endif;?> type="checkbox" item_id="<?php echo $_item->getId();?>" is_imported="<?php echo $_product->getData('is_imported');?>" name="selectitem[<?php echo $_item->getId();?>]" class="selectitem" />
确认按钮:
<button type="button" id="select_need_btn" name="select_need_btn" value="empty_cart" title="<?php echo $this->__('Checkout'); ?>" class="button btn-empty" ><span><span><?php echo $this->__('Proceed to Checkout'); ?></span></span></button>
前台ajax:
<script> (function($){ $('.btn-proceed-checkout').hide(); //全选 $('.select_all_cb').click(function(){ if (this.checked) { $('.selectitem').attr('checked',true); } else { $('.selectitem').attr('checked',false); } }) $('#select_need_btn').click(function(){ //点击需要结账的按钮。选好复选框。 var item_id_str = ''; $('.selectitem:checked').each(function() { item_id_str += ($(this).attr('item_id')) + ','; }) if (item_id_str == '') { alert('<?php echo $this->__('Please check items!');?>'); return ; } $.ajax({ url:'<?php echo $this->getUrl('checkout/cart/selectitem')?>', type:'post', data:'item_id_str='+item_id_str, async : false, //默认为true 异步 error:function(){ alert('error'); }, success:function(data){ if (data == '0') { alert('Please specify only imported or domesitc products'); return; } else { $(".item_tbody").html(data); $('.select_all_cb').attr('checked',false); $('.btn-proceed-checkout').click(); } } }); }) })(jQuery); </script>
处理选中的item, 这里有个额外需求。将进口商品和国内商品分开结算,也就是当选中商品既包含国外也包含国内的时候不执行任何操作,返回错误代码0. 如果只选中了国内,或者只选中了进口,就把未选中的数据从数据库备份起来以备之后的回复,然后讲他们从从原生表里删除,重新计算购物车价格:
继承声明:
<frontend> <routers> <checkout> <use>standard</use> <args> <modules> <Super_Awesome before="Mage_Checkout">Bysoft_Mycheckout</Super_Awesome> </modules> </args> </checkout> </routers> </frontend>
继承类具体实现:
class Bysoft_Mycheckout_CartController extends Mage_Checkout_CartController
{
public function selectitemAction(){
$item_id_str = Mage::app()->getRequest()->getParam('item_id_str');
$item_id_arr = explode(',' , $item_id_str);
$the_item_ids = array();
foreach ($item_id_arr as $key=>$val) {
if ((int)trim($val)!= '0') {
$the_item_ids[] = $item_id_arr[$key] = (int)trim($val);
}
}
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();
$exists_imported = false;
$exists_domesitc = false;
foreach ($cartItems as $item) {
if (in_array($item->getId(), $the_item_ids)) {
$product_id = $item->getProductId();
$product = Mage::getModel('catalog/product')->load($product_id);
if ($product->getData('is_imported') == 1) {
$exists_imported = true;
break;
}
}
}
foreach ($cartItems as $item) {
if (in_array($item->getId(), $the_item_ids)) {
$product_id = $item->getProductId();
$product = Mage::getModel('catalog/product')->load($product_id);
if ($product->getData('is_imported') == 0) {
$exists_domesitc = true;
break;
}
}
}
if ($exists_imported && $exists_domesitc) {
echo 0;
} else {
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$cartData = array();
//set staus for quote item
$cartHelper = Mage::helper('checkout/cart');
$items = $cartHelper->getCart()->getItems();
foreach ($items as $item) {
if (in_array($item->getId(), $the_item_ids) || in_array($item->getData('parent_item_id'),$the_item_ids)) {
//需要保留的行
$this->set_selected_item($item->getId(),1);
//从备份表里删除
$this->delete_from_back($item->getId());
} else {
//需要移动的行
$this->set_selected_item($item->getId(),0);
//放入备份表
$this->move_core_to_back($item->getId());
}
}
//重新计算购物车总价
$quote->setTotalsCollectedFlag(false)->collectTotals();
$quote->save();
$simple_block = $this->getLayout()->createBlock('checkout/cart_item_renderer');
$config_block = $this->getLayout()->createBlock('checkout/cart_item_renderer_configurable');
$group_block = $this->getLayout()->createBlock('checkout/cart_item_renderer_grouped');
$html = '';
foreach($cartItems as $item) {
if ($item->getData('product_type') == 'simple') {
$block = $simple_block;
} else if ($item->getData('product_type') == 'configurable') {
$block = $config_block;
} else {
$block = $group_block;
}
$html .= $block->setTemplate('checkout/cart/item/default.phtml')->setItem($item)->toHtml();
}
if ($exists_domesitc && $exists_imported) {
echo $html;
} else {
echo $html;
}
}
}
protected function _getCart()
{
return Mage::getSingleton('checkout/cart');
}
/**
* 移动未选中数据到备份表
* @param unknown $item_id
*/
public function move_core_to_back($item_id) {
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql ="delete from bysoft_sales_flat_quote_item where item_id = ?";
$write->query($sql,array($item_id));
$sql = "insert into bysoft_sales_flat_quote_item select * from sales_flat_quote_item where item_id = ?";
$write->query($sql,array($item_id));
$sql = "delete from bysoft_sales_flat_quote_item_option where item_id = ?";
$write->query($sql,array($item_id));
$sql = "insert into bysoft_sales_flat_quote_item_option select * from sales_flat_quote_item_option where item_id = ?";
$write->query($sql,array($item_id));
}
/**
* 将item从备份表删除
*/
public function delete_from_back($item_id) {
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql ="delete from bysoft_sales_flat_quote_item where item_id = ?";
$write->query($sql,array($item_id));
$sql = "delete from bysoft_sales_flat_quote_item_option where item_id = ?";
$write->query($sql,array($item_id));
}
/**
* 设定Item的选中状态
* @param unknown $item_id
* @param unknown $status
*/
public function set_selected_item($item_id, $status) {
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql = "update sales_flat_quote_item set selected_item = ? where item_id = ?";
$write->query($sql, array($status, $item_id));
}
在完成选择Item之后页面就到了checkout页面。
选好支付和shipping之后,有两种步骤。
第一种是返回上一页。恢复item到核心表。
public function recover_item() {
$quote_id = Mage::getSingleton('checkout/session')->getQuoteId();
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql = "insert into sales_flat_quote_item select * from bysoft_sales_flat_quote_item where quote_id = ? and item_id not in (select item_id from sales_flat_quote_item)";
$write->query($sql, array($quote_id));
$sql = "insert into sales_flat_quote_item_option select * from bysoft_sales_flat_quote_item_option where item_id in (select item_id from bysoft_sales_flat_quote_item where quote_id = ? ) and option_id not in (select option_id from sales_flat_quote_item_option)";
$write->query($sql, array($quote_id));
$sql = "delete from bysoft_sales_flat_quote_item_option where item_id in (select item_id from bysoft_sales_flat_quote_item where quote_id =?)";
$write->query($sql, array($quote_id));
$sql = "delete from bysoft_sales_flat_quote_item where quote_id = ?";
$write->query($sql, array($quote_id));
try {
$quote = Mage::getSingleton('checkout/session')->getQuote();
$quote->setTotalsCollectedFlag(false)->collectTotals();
$quote->save();
} catch (Exception $e) {
echo $e->getMessage();
exit();
}
}
public function indexAction(){
$this->recover_item();
$cart = $this->_getCart();
if ($cart->getQuote()->getItemsCount()) {
$cart->init();
$cart->save();
if (!$this->_getQuote()->validateMinimumAmount()) {
$minimumAmount = Mage::app()->getLocale()->currency(Mage::app()->getStore()->getCurrentCurrencyCode())
->toCurrency(Mage::getStoreConfig('sales/minimum_order/amount'));
$warning = Mage::getStoreConfig('sales/minimum_order/description')
? Mage::getStoreConfig('sales/minimum_order/description')
: Mage::helper('checkout')->__('Minimum order amount is %s', $minimumAmount);
$cart->getCheckoutSession()->addNotice($warning);
}
}
// Compose array of messages to add
$messages = array();
foreach ($cart->getQuote()->getMessages() as $message) {
if ($message) {
// Escape HTML entities in quote message to prevent XSS
$message->setCode(Mage::helper('core')->escapeHtml($message->getCode()));
$messages[] = $message;
}
}
$cart->getCheckoutSession()->addUniqueMessages($messages);
/**
* if customer enteres shopping cart we should mark quote
* as modified bc he can has checkout page in another window.
*/
$this->_getSession()->setCartWasUpdated(true);
Varien_Profiler::start(__METHOD__ . 'cart_display');
$this
->loadLayout()
->_initLayoutMessages('checkout/session')
->_initLayoutMessages('catalog/session')
->getLayout()->getBlock('head')->setTitle($this->__('Shopping Cart'));
$this->renderLayout();
Varien_Profiler::stop(__METHOD__ . 'cart_display');
}
第二种则是下单,在下单完成后恢复备份表里的数据到核心表
需要覆盖原生OnepageController内的successAction
public function successAction()
{
$session = $this->getOnepage()->getCheckout();
if (!$session->getLastSuccessQuoteId()) {
$this->_redirect('checkout/cart');
return;
}
$lastQuoteId = $session->getLastQuoteId();
$lastOrderId = $session->getLastOrderId();
$lastRecurringProfiles = $session->getLastRecurringProfileIds();
if (!$lastQuoteId || (!$lastOrderId && empty($lastRecurringProfiles))) {
$this->_redirect('checkout/cart');
return;
}
$session->clear();
$this->add_back_cart_item($lastQuoteId);
$this->loadLayout();
$this->_initLayoutMessages('checkout/session');
Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
$this->renderLayout();
}
public function add_back_cart_item($old_quote_id) {
// get logged in cusomer id
$customerAccountNo = Mage::getModel('customer/session')->getCustomer()->getId();
// load customer object
$customerObj = Mage::getModel('customer/customer')->load($customerAccountNo);
// assign this customer to quote object, before any type of magento order, first create quote.
$quoteObj = Mage::getModel('sales/quote')->assignCustomer($customerObj);
$quoteObj->setStoreId(Mage::app()->getStore()->getId())->save();
$new_quote_id = $quoteObj->getData('entity_id');
Mage::log($quoteObj->getData('entity_id'));
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$sql = "update bysoft_sales_flat_quote_item set quote_id = ? where quote_id=?";
$write->query($sql, array($new_quote_id, $old_quote_id));
$sql = "insert into sales_flat_quote_item select * from bysoft_sales_flat_quote_item where quote_id = ?";
$write->query($sql, array($new_quote_id));
$sql = "insert into sales_flat_quote_item_option select * from bysoft_sales_flat_quote_item_option where item_id in (select item_id from bysoft_sales_flat_quote_item where quote_id =?)";
$write->query($sql, array($new_quote_id));
$quote = Mage::getSingleton('checkout/session')->getQuote();
$quote->setTotalsCollectedFlag(false)->collectTotals();
$quote->save();
}