Magento 1.9 从购物车通过脚本创建订单报错及疑问
我来帮你拆解这两个Magento订单创建的问题,结合实战经验给你解决方案:
一、如何从购物车页面调用脚本正常工作
500服务器错误通常是权限冲突、Magento应用重复初始化,或者未捕获的代码错误导致的,你可以按以下步骤排查修复:
先开启错误提示,定位具体问题
模糊的500错误很难排查,先在脚本开头添加以下代码,强制显示所有错误信息:ini_set('display_errors', 1); error_reporting(E_ALL); Mage::setIsDeveloperMode(true);避免重复初始化Magento应用
在checkout/cart这类前端页面中,Magento已经完成了应用初始化,重复执行Mage::app()会引发会话或配置冲突。你可以先判断应用状态,再使用当前请求的店铺:if (!Mage::isInstalled()) { exit('Magento未安装,请检查配置'); } // 使用当前请求的店铺,而非硬编码default $store = Mage::app()->getStore();改用Magento控制器处理逻辑,不要直接调用独立脚本
直接访问独立PHP脚本会跳过Magento的会话验证、路由机制,容易出现权限不足或会话丢失的问题。推荐创建自定义模块的控制器动作来处理订单创建:- 新建自定义模块(比如
Custom_OrderCreator),在controllers目录下创建CartController.php:<?php require_once 'Mage/Checkout/controllers/CartController.php'; class Custom_OrderCreator_CartController extends Mage_Checkout_CartController { public function createOrderAction() { // 这里编写你的订单创建逻辑 $quote = Mage::getSingleton('checkout/cart')->getQuote(); // 设置账单/收货地址 $billingAddress = array( 'firstname' => 'Me', 'lastname' => 'And', 'company' => 'None', 'email' => 'asdf@asdf.com', 'street' => array( 'Sample Street Line_1', 'Sample Street Line_2' ), 'city' => 'City', 'region_id' => '', 'region' => 'State/Province', 'postcode' => '12345', 'country_id' => 'DE', 'telephone' => '1234567890', 'fax' => '123456987', 'save_in_address_book' => '0', 'use_for_shipping' => '1', ); $quote->getBillingAddress()->addData($billingAddress); $quote->getShippingAddress()->addData($billingAddress) ->setShippingMethod('solutioo') ->setPaymentMethod('cashondelivery') ->setCollectShippingRates(true); // 设置访客结账 $quote->setCheckoutMethod('guest') ->setCustomerId(null) ->setCustomerEmail($quote->getBillingAddress()->getEmail()) ->setCustomerIsGuest(true) ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID); // 设置支付方式 $quote->getPayment()->importData(array('method' => 'cashondelivery')); // 计算总额并保存Quote $quote->collectTotals()->save(); // 提交订单 $service = Mage::getModel('sales/service_quote', $quote); $service->submitAll(); // 跳转至成功页面 $this->_redirect('checkout/onepage/success'); } } - 在购物车页面添加一个提交按钮,通过POST请求到这个控制器动作:
<form action="<?php echo $this->getUrl('ordercreator/cart/createOrder'); ?>" method="post"> <button type="submit">直接创建订单</button> </form>
这种方式能继承Magento的会话和权限控制,避免独立脚本的各种问题。
- 新建自定义模块(比如
检查文件权限
确保Web服务器用户(比如www-data)对Magento的var/、media/目录有写入权限,脚本文件权限设置为644,目录权限设置为755,避免因权限不足导致的写入失败。
二、商品获取方式是否正确?
你当前的代码存在明显错误:
$product = Mage::getSingleton('checkout/cart')->getItems(); $quote->addProduct($product, new Varien_Object($buyInfo));
getItems()返回的是购物车商品的Quote Item集合(Mage_Sales_Model_Quote_Item对象的集合),而$quote->addProduct()方法需要传入的是Mage_Catalog_Model_Product实例或产品ID,直接传入集合会触发类型错误。
正确的处理方式分两种场景:
直接将当前购物车转换成订单
不需要重新创建新的Quote,直接使用当前购物车已有的Quote即可,它已经包含了所有商品信息:// 获取当前购物车的Quote,已包含所有商品、数量等信息 $quote = Mage::getSingleton('checkout/cart')->getQuote();从购物车提取商品,添加到新的Quote中
如果需要创建新的Quote(比如复制购物车商品到新订单),需要遍历购物车的商品集合,逐个获取对应的产品模型,再添加到新Quote:$cartItems = Mage::getSingleton('checkout/cart')->getItems(); $newQuote = Mage::getModel('sales/quote')->setStoreId(Mage::app()->getStore()->getId()); foreach ($cartItems as $item) { $product = $item->getProduct(); // 获取对应的产品模型 $buyInfo = array('qty' => $item->getQty()); // 使用购物车中的商品数量 $newQuote->addProduct($product, new Varien_Object($buyInfo)); }
额外注意事项:
在提交订单前,一定要调用collectTotals()方法计算订单总额,否则会出现金额计算错误:
$quote->collectTotals()->save();
内容的提问来源于stack exchange,提问作者Tyv

