【问题标题】:Control the number of results from a Magento API call控制 Magento API 调用的结果数量
【发布时间】:2011-10-17 16:26:57
【问题描述】:

我有一个程序,用于通过 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 循环开销并使程序更有效地运行,因为它只获取所需的数据。

有谁知道如何应用这种类型的过滤器?我所看到的一切都表明,只有在您知道订单号并以此为基础设置限制的情况下,您才能这样做。谢谢你的帮助!!!

【问题讨论】:

  • +1 表达清楚的问题。
  • 我相信这个问题已经解决了,但值得一提的是,Magento 的 REST API 支持分页和限制。

标签: php api magento


【解决方案1】:

所有 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 文件后,仔细搜索它们,以确定哪个配置了您的“顶级 api 命名空间”(不确定内部开发人员真正调用的是什么)

$ 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 是我们想要的文件,因为它有一个&lt;sales_order /&gt; 标签。接下来,打开文件并查看&lt;sales_order /&gt; 节点。

<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>

我们感兴趣的第一个节点是&lt;model&gt;sales/order_api&lt;/model&gt;。这指定将被实例化以处理 sales_order 命名空间中的任何 API 调用的对象。

接下来,我们将在&lt;methods/&gt; 节点中查找方法list

<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'=&gt;'10','to'=&gt;'20') 语法的某种日期过滤器。

您的第二个选择是为 Mage_Sales_Model_Order_Api::items 创建一个类重写,它会进行一些额外的过滤。

您的第三个选择是研究创建一个添加自定义 API 方法供您调用的模块。

【讨论】:

  • 这是回溯 API 方法的 101 分,Alan。我相信这对很多用户来说会很有帮助(至少对于那些真正在询问之前使用搜索的用户来说是这样的^^)。 +1 并添加到收藏夹。
  • 优秀的教程,正是我所需要的,并帮助我将整个问题推向了更好的解决方案。非常感谢!
【解决方案2】:

设置限制的快速解决方案是找到 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 调用。

嘘!

【讨论】:

    【解决方案3】:

    您应该能够使用 setPage,它通过指定页码(单索引)和每页的记录数来设置查询 LIMIT 子句。

    $collection->setPage($pageNum, $pageSize);
    

    要选择第二组 10 个项目,您可以使用以下命令:

    $collection->setPage(2, 10);
    

    可以在此处找到有关此主题的更多信息:Using Collections in Magento

    【讨论】:

    • 标准 Magento Sales_Order API 不允许直接传递限制。 OP 需要覆盖 Mage_Sales_Model_Order_Api::items() 才能这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多