题
我遇到了不同的方式来编程创建货物。他们是
//Type 1
$converter=Mage::getModel('sales/convert_order');
$shipment=$converter->toShipment($order);
// snip
//Type 2
$shipment = Mage::getModel('sales/service_order', $order)
->prepareShipment($this->_getItemQtys($order));
// snip
//Type 3
$shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQty);
$shipment = new Mage_Sales_Model_Order_Shipment_Api();
$shipmentId = $shipment->create($orderId);
// snip
这些方法之间有什么区别。三种方法的out是创建货物和添加跟踪数字的正确方法。
解决方案
我会试一试。让我们一次带他们一个:
方法1
$converter=Mage::getModel('sales/convert_order');
$shipment=$converter->toShipment($order);
$converter
以上是从班级加载的 Mage_Sales_Model_Convert_Order
, ,使用核心助手称为 copyFieldset
将订单详细信息复制到装运对象中。 $订单必须是类型数组或 Varien_Object
.
该方法实际上是方法3的核心,因为它使用 Mage::getModel('sales/convert_order')
在其构造函数中。
钥匙区分 此方法 - 它可以采用数组或对象 $order
并生成基本 $shipment
目的。这是您在方法2,方法3中提出的方法仅使用的低级方法。
方法2
$shipment = Mage::getModel('sales/service_order', $order)
->prepareShipment($this->_getItemQtys($order));
这似乎是Magento生成货物的核心中最受欢迎的方式,因为它在发货和发票控制器中都使用。 $order
用作实例化的构造函数论点 Mage_Sales_Model_Service_Order
, ,将其设置为对象上的受保护属性。
然后您打电话 prepareShipment
并通过数量。由于此方法使用方法1的转换器类,您 不需要指定更多详细信息,例如订单项目 通过物品发货的数量详细信息 prepareShipment
参数,在这里称为 $this->_getItemQtys
. 。要在您自己的上下文中使用它,您需要做的就是以以下格式传递数组中的项目数量:
array(
'order_item_id'=>$qty,
'order_item_id'=>$qty,
'order_item_id'=>$qty
)
钥匙区分 在此方法中 - 它使您可以回到$运输对象,但是所有项目都会转换为其中。它是插件。
方法3
我找不到在核心中使用此方法的证据。老实说,它看起来像是一个黑客。这是方法:
$itemQty = $order->getItemsCollection()->count();
$shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQty);
$shipment = new Mage_Sales_Model_Order_Shipment_Api();
$shipmentId = $shipment->create($orderId);
步骤1与上面的方法2完全相同。没有不同。但是,你回来了 $shipment
物体,被直接固定的替代 Mage_Sales_Model_Order_Shipment_Api
. 。这是非标准的。获得装运API对象的最佳实践方法是致电 Mage::getModel('sales/order_shipment_api')
.
接下来,它使用覆盖的新装运API对象来创建一个从 $orderId
在您的代码中尚未定义的变量。同样,这似乎是解决方法。
看着 Mage_Sales_Model_Order_Shipment_Api::create()
, ,似乎是一站式发货的一站式服务 increment_id
.
这是任何模块或扩展名不应使用的黑客。该API的目的是通过XML RPC / SOAP API请求暴露的功能消耗,并且有意基本消除了多个步骤API请求。
最终,方法3到达nitty-gritty,并通过呼叫mage_sales_model_order来调用 prepareShipment
, ,这是上述熟悉方法2的高阶抽象:
public function prepareShipment($qtys = array())
{
$shipment = Mage::getModel('sales/service_order', $this)->prepareShipment($qtys);
return $shipment;
}
关键区别在这里 - 如果您需要发货,请不要介意hacks,只有一个rezement_id-使用此方法。如果您希望通过SOAP API处理此操作,也有用的信息。
我希望这会有所帮助。
其他提示
这里的关键是方法1和2不起作用...
我同意@philwinkle,方法3是骇人听闻的。在非API上下文中,不应真正调用API函数。您永远不知道未来发布可能会带来什么来打破这种代码。
那离开什么?好吧,方法1和2并没有完全破坏。只是他们只做一部分工作。这就是他们应该的样子:
注意:简而言之,以下代码片段将向发货添加所有合格的物品。如果您只想运送订单的一部分,则必须修改代码的某些部分 - 希望我给您足够的时间继续。
方法1
如果您查看代码 app/code/core/Mage/Sales/Model/Order/Shipment/Api.php
(如方法3中所述),您还可以看到 $convertor->toShipment($order)
它也打电话 $item = $convertor->itemToShipmentItem($orderItem)
, $item->setQty($qty)
和 $shipment->addItem($item)
对于每个合格的订单项目。是的,Magento真的很懒惰,您必须哄骗它。单身的。步。然后,您必须跳过几个篮球,才能将货物实际保存在数据库中。
所以方法1应该看起来像这样:
$convertor = Mage::getModel('sales/convert_order');
$shipment = $convertor->toShipment($order);
foreach ($order->getAllItems() as $orderItem) {
if ($orderItem->getQtyToShip() && !$orderItem->getIsVirtual()) {
$item = $convertor->itemToShipmentItem($orderItem);
$item->setQty($orderItem->getQtyToShip());
$shipment->addItem($item);
}
}
$shipment->register();
$order->setIsInProcess(true);
Mage::getModel('core/resource_transaction')
->addObject($shipment)
->addObject($order))
->save();
方法2
首先,您要打电话 $this->_getItemQtys()
当然,这只能在某些类中工作(具有或继承_getItemqtys函数的类别,natch)。因此,需要更改,并且与方法1一样,您还需要充实过程。
看 app/code/core/Mage/Adminhtml/controllers/Sales/Order/ShipmentController.php
这种方法的情况稍好一些 - 似乎这些物品与货物本身一起转换了。但是,您仍然只需收回一个瞬态对象,您必须自己保存到数据库中,就像这样:
$itemQtys = array();
foreach ($order->getAllItems() as $orderItem) {
if ($orderItem->getQtyToShip() && !$orderItem->getIsVirtual()) {
$itemQtys[$orderItem->getId()] = $orderItem->getQtyToShip();
}
}
$shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($itemQtys);
$shipment->register();
$order->setIsInProcess(true);
Mage::getModel('core/resource_transaction')
->addObject($shipment)
->addObject($order)
->save();
我还建议在其中添加一些错误检查,例如,确保您的发货实际上包含任何物品 register()
它。
哪个最好?
我会说这是一个意见问题。我没有进行任何基准测试,但是我非常有信心两种方法之间的速度差异可以忽略不计。至于代码尺寸和可读性,它们之间没有太多。
我确实喜欢Method 2,因为不必明确转换订单中的所有项目,但它仍然需要您通过它们来提取数量。对于不错的小型代码足迹,方法3将是我的最爱!但是作为软件工程师,我不建议这样做。因此,我将大吃一惊。
伙计们以上都没有在我的问题上奏效。以下对我有用。将其放在这里,以防万一它可以帮助你们中的任何人。
public function _createShipment($orderIncrementId = '100310634'){
// Load Product ..
$order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
// Create Qty array
$shipmentItems = array();
foreach ($order->getAllItems() as $item) {
$shipmentItems [$item->getId()] = $item->getQtyToShip();
}
// Prepear shipment and save ....
if ($order->getId() && !empty($shipmentItems) && $order->canShip()) {
$shipment = Mage::getModel('sales/service_order', $order)->prepareShipment($shipmentItems);
$shipment->save();
}
}