控制 Magento API 调用的结果数量

发布于 2024-12-10 18:53:36 字数 1108 浏览 1 评论 0原文

我有一个程序,用于通过 API 将 Magento 商店连接到后端库存控制系统。目前它的作用是查询 Magento API 中所有处于 Pending 状态的订单,将它们插入后端系统,然后将它们的状态设置为 Magento 中的“正在处理”。由于我们的库存系统的限制,我们一次只能插入有限数量的订单。我们通过 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 循环开销并使程序运行更有效,因为它只获取所需的数据。

有谁知道如何应用这种类型的过滤器?我所看到的一切都表明,只有当您知道订单号并据此设置限制时,您才能执行此操作。感谢您的帮助!!!

I have a program that we use to connect our Magento store to our back end Inventory Control system via the API. Currently what it does is query the Magento API for all orders in Pending status, inserts them into the back end system, then sets their status to Processing in Magento. Due to limitations on our Inventory system, we can only insert a limited number of orders at a time. We control this by running the whole process through an if loop as shown below (FYI, code has been edited down to show only the key parts of this problem):

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

The obvious downfall of doing it this way is I still have to pull all Pending orders even though I am going to be working with only 10 of them. i.e. If I have 200 pending orders, the API returns all 200 of them, processes 10, then skips the rest. What I want to do is modify the filter of the API call to pull only 10 orders at a time of status Processing. This would allow me to remove the if loop overhead and make the program run more efficiently because it only gets the data it needs.

Does anyone know how to apply that type of filter? Everything I have seen suggest you can only do this if you know the order numbers and set limits based on that. Thanks for your help!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑾夏年华 2024-12-17 18:53:36

所有 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 是我们想要的文件,因为它有 标签。接下来,打开文件并查看 节点。

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

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

接下来,我们将在 节点中查找方法 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());
        }
    }        
}

在此方法的末尾,您可以看到该方法将遍历每个参数并尝试将其用作集合的过滤器。键是字段,值是要搜索的值。如果您检查该方法的其余部分,您会发现没有其他方法可以使参数与集合交互来添加任何类型的分页或限制。

因此,这给您提供了三个选择。第一个是找到一组值传递给

$collection->addFieldToFilter($field, $value);

这将限制您的集合。我的建议是使用 array('from'=>'10','to'=>'20') 语法进行某种日期过滤器。

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

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

All API calls are, eventually, just executed PHP code. There will be a single PHP method somewhere that accepts the arguments passed in via the API call, so your best bet is to track down where that PHP code is executed.

Step 1 is to find the API call's configuration. In modern versions of Magento, API configurations are kept in files named 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

Once you've found all the api.xml files, search through them to fine which one configures your "top level api namespace" (unsure what this is really called by the internal developers)

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

It looks like app/code/core/Mage/Sales/etc/api.xml is the file we want, since it has a <sales_order /> tag. Next, open the file and look at the <sales_order /> node.

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

The first node we're interested in is <model>sales/order_api</model>. This specifies the object that will be instantiated to handle any API call in the sales_order namespace.

Next, we're going to look for the method list in the <methods/> node.

<list translate="title" module="sales">
    <title>Retrieve list of orders by filters</title>
    <method>items</method>
    <acl>sales/order/info</acl>
</list>

This node tells us that a call to sales_order.list corresponds to the method items. Combining that with the information found above, we now know the API call sales_order.list will run PHP code equivalent to the following

$m = Mage::getModel('sales/order_api');
$results = $m->items($args);

Next, open your model file and look at the items method

#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());
        }
    }        
}

At the end of this method, you can see that the method will run through each argument and attempt to use it as a filter on the collection. The key is the field, the value is the value search for. If you inspect the rest of the method you'll see there's no other way the paramaters interact with the collection to add any sort of paging or limits.

So, this leaves you with three options. The first is to find a set of values to pass into

$collection->addFieldToFilter($field, $value);

that will limit your collection. My suggestion would be some sort of date filter using the array('from'=>'10','to'=>'20') syntax.

Your second option would be to create a class rewrite for Mage_Sales_Model_Order_Api::items that does some extra filtering.

Your third option would be to investigate creating a module that adds a custom API method for you to call.

很糊涂小朋友 2024-12-17 18:53:36

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

嘘!

A quick solution to set a limit is to locate app/code/core/Mage/Sales/Model/Order/Api.php (and do an overwrite of the class) then:

Change the method signature to accept another parameter $limit so the method signature looks like:

public function items($filters = null, $limit = null)

Then, add the following line before "foreach ($orderCollection as $order) {":

if( $limit ) $orderCollection->setPageSize( $limit );

Then simply pass the limit as an extra argument to the sales_order.list api call.

Booyah!

零度° 2024-12-17 18:53:36

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

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

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

$collection->setPage(2, 10);

有关此主题的更多信息可以在此处找到:在 Magento 中使用集合

You should be able to use setPage, which sets the query LIMIT clause by specifying page number (one-indexed) and number of records per page.

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

To select the second set of 10 items, you would use the following:

$collection->setPage(2, 10);

More information on this topic can be found here: Using Collections in Magento

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文