我有一个程序,我们用它通过API将我们的Magento商店连接到我们的后端库存控制系统。目前它所做的是查询Magento API以获取处于Pending状态的所有订单,将它们插入后端系统,然后将其状态设置为Magento中的Processing。由于我们的库存系统存在限制,我们一次只能插入有限数量的订单。我们通过if循环运行整个过程来控制它,如下所示(仅供参考,代码已经过编辑,仅显示此问题的关键部分):
//The maximum number of orders to download
$iMaxCount = 10 ;
try {
$proxy = new SoapClient($wsdl_url);
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
$sessionId = $proxy->login($login, $password);
//fetch the pending orders from the site
$field = array(array('status'=>array( 'pending') ));
$arr = $proxy->call($sessionId, 'sales_order.list', $field);
$iCnt = 0;
foreach($arr as $key => $value){
//only down up to the max count
if ($iCnt < $iMaxCount) {
[... Do the updating and insertion part of the program ...]
$iCnt++;
} //End of looping through orders
以这种方式这样做的明显垮台是我仍然需要拉出所有待定订单,即使我将只与其中的10个一起工作。即如果我有200个待处理订单,API将返回所有200个订单,处理10,然后跳过其余订单。我想要做的是修改API调用的过滤器,以便在状态处理时仅提取10个订单。这将允许我删除if循环开销并使程序运行更高效,因为它只获取它需要的数据。
有谁知道如何应用这种类型的过滤器?我见过的所有内容都建议您只有在知道订单号并基于此设置限制时才能执行此操作。谢谢你的帮助!!!
答案 0 :(得分:18)
所有API调用最终都只是执行PHP代码。在某处可以使用单个PHP方法接受通过API调用传入的参数,因此最好的办法是跟踪PHP代码的执行位置。
第1步是找到API调用的配置。在现代版本的Magento中,API配置保存在名为api.xml
$ find app/code/core/Mage/ -name 'api.xml'
app/code/core/Mage/Api/etc/api.xml
app/code/core/Mage/Catalog/etc/api.xml
app/code/core/Mage/CatalogInventory/etc/api.xml
app/code/core/Mage/Checkout/etc/api.xml
app/code/core/Mage/Customer/etc/api.xml
app/code/core/Mage/Directory/etc/api.xml
app/code/core/Mage/GiftMessage/etc/api.xml
app/code/core/Mage/Sales/etc/api.xml
一旦找到所有api.xml
个文件,请仔细搜索它们以确定哪个文件配置了您的&#34;顶级api命名空间&#34; (不确定内部开发人员真正称之为什么)
$ find app/code/core/Mage/ -name 'api.xml' | xargs grep sales_order
app/code/core/Mage/Sales/etc/api.xml: <sales_order translate="title" module="sales">
app/code/core/Mage/Sales/etc/api.xml: </sales_order>
app/code/core/Mage/Sales/etc/api.xml: <sales_order_shipment>
app/code/core/Mage/Sales/etc/api.xml: </sales_order_shipment>
app/code/core/Mage/Sales/etc/api.xml: <sales_order_invoice>
app/code/core/Mage/Sales/etc/api.xml: </sales_order_invoice>
app/code/core/Mage/Sales/etc/api.xml: <order>sales_order</order>
app/code/core/Mage/Sales/etc/api.xml: <order_shipment>sales_order_shipment</order_shipment>
app/code/core/Mage/Sales/etc/api.xml: <order_invoice>sales_order_invoice</order_invoice>
看起来app/code/core/Mage/Sales/etc/api.xml
是我们想要的文件,因为它有一个<sales_order />
标记。接下来,打开文件并查看<sales_order />
节点。
<sales_order translate="title" module="sales">
<model>sales/order_api</model>
<title>Order API</title>
<acl>sales/order</acl>
<methods>
<list translate="title" module="sales">
<title>Retrieve list of orders by filters</title>
<method>items</method>
<acl>sales/order/info</acl>
</list>
<info translate="title" module="sales">
<title>Retrieve order information</title>
<acl>sales/order/info</acl>
</info>
我们感兴趣的第一个节点是<model>sales/order_api</model>
。这指定了将被实例化以处理sales_order
命名空间中的任何API调用的对象。
接下来,我们将在list
节点中查找方法<methods/>
。
<list translate="title" module="sales">
<title>Retrieve list of orders by filters</title>
<method>items</method>
<acl>sales/order/info</acl>
</list>
此节点告诉我们对sales_order.list
的调用对应于方法items
。结合上面的信息,我们现在知道API调用sales_order.list
将运行与以下相同的PHP代码
$m = Mage::getModel('sales/order_api');
$results = $m->items($args);
接下来,打开模型文件并查看items
方法
#File: app/code/core/Mage/Sales/Model/Order/Api.php
public function items($filters = null)
{
//..a bunch of code to instantiate a collection object..
if (is_array($filters)) {
try {
foreach ($filters as $field => $value) {
if (isset($this->_attributesMap['order'][$field])) {
$field = $this->_attributesMap['order'][$field];
}
$collection->addFieldToFilter($field, $value);
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
}
}
}
在此方法结束时,您可以看到该方法将遍历每个参数并尝试将其用作集合的过滤器。关键是字段,值是值搜索。如果您检查方法的其余部分,您将看到参数与集合交互以添加任何类型的分页或限制。
所以,这给你留下了三个选择。第一个是find a set of values进入
$collection->addFieldToFilter($field, $value);
这将限制您的收藏。我的建议是使用array('from'=>'10','to'=>'20')
语法的某种日期过滤器。
你的第二个选择是为Mage_Sales_Model_Order_Api::items
创建一个类重写,进行一些额外的过滤。
您的第三个选择是调查创建一个模块,该模块添加了一个自定义API方法供您调用。
答案 1 :(得分:1)
设置限制的快速解决方案是找到app / code / core / Mage / Sales / Model / Order / Api.php(并覆盖该类)然后:
更改方法签名以接受另一个参数$ limit,以便方法签名如下所示:
public function items($filters = null, $limit = null)
然后,在“foreach($ orderCollection as $ order){”之前添加以下行:
if( $limit ) $orderCollection->setPageSize( $limit );
然后简单地将限制作为额外参数传递给sales_order.list api调用。
Booyah!
答案 2 :(得分:0)
您应该能够使用setPage,它通过指定页码(一个索引)和每页的记录数来设置查询LIMIT子句。
$collection->setPage($pageNum, $pageSize);
要选择第二组10个项目,您将使用以下内容:
$collection->setPage(2, 10);
有关此主题的更多信息,请访问:Using Collections in Magento