У меня есть программа, которую мы используем для подключения нашего магазина Magento к нашей системе управления запасами через API. В настоящее время он выполняет запрос API Magento для всех заказов в состоянии ожидания, вставляет их в заднюю систему, а затем устанавливает их статус «Обработка в Magento». Из-за ограничений в нашей системе инвентаризации мы можем вставлять только ограниченное количество заказов за раз. Мы контролируем это, запустив весь процесс через цикл if, как показано ниже (FYI, код был отредактирован, чтобы показать только ключевые части этой проблемы):
//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 и сделать программу более эффективной, поскольку она получает только нужные ему данные.
Кто-нибудь знает, как применять этот тип фильтра? Все, что я видел, предполагает, что вы можете сделать это только в том случае, если знаете номера заказов и установите ограничения на основе этого. Спасибо за вашу помощь!!!
Все вызовы 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
и$ 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
и$ 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
и$ 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
и$ 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
и$ 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
и$ 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
и$ 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.xml
поиск через них, чтобы настроить, какой из них «пространство имен api верхнего уровня» (не знаете, что это действительно api.xml
внутренними разработчиками)
$ 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>
. Это указывает объект, который будет создан для обработки любого вызова API в пространстве имен sales_order
.
Затем мы рассмотрим list
<methods/>
узле <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()); } } }
В конце этого метода вы увидите, что метод будет проходить через каждый аргумент и попытаться использовать его в качестве фильтра в коллекции. Ключ – это поле, значение – это поиск значения. Если вы проверите оставшуюся часть метода, вы увидите, что нет другого способа взаимодействия параметров с коллекцией, чтобы добавить какой-либо пейджинг или лимиты.
Таким образом, это оставляет вам три варианта. Первый заключается в том, чтобы найти набор значений для перехода в
$collection->addFieldToFilter($field, $value);
что ограничит вашу коллекцию. Мое предложение было бы каким-то фильтром даты, используя array('from'=>'10','to'=>'20')
синтаксис.
Второй вариант заключается в создании перезаписи класса для Mage_Sales_Model_Order_Api::items
которые выполняют некоторую дополнительную фильтрацию.
Третий вариант – исследовать создание модуля, который добавит настраиваемый метод API для вызова.
Быстрое решение установить ограничение – найти приложение / код / ядро / Маг / Продажи / Модель / Заказ / Api.php (и выполнить переписывание класса), затем:
Измените подпись метода, чтобы принять другой параметр $ limit, поэтому подпись метода выглядит так:
public function items($filters = null, $limit = null)
Затем добавьте следующую строку перед «foreach ($ orderCollection as $ order) {":
if( $limit ) $orderCollection->setPageSize( $limit );
Затем просто передайте лимит в качестве дополнительного аргумента для вызова api sales_order.list.
Booyah!
Вы должны иметь возможность использовать setPage, который устанавливает предложение LIMIT запроса, указывая номер страницы (одноиндексированный) и количество записей на странице.
$collection->setPage($pageNum, $pageSize);
Чтобы выбрать второй набор из 10 элементов, вы должны использовать следующее:
$collection->setPage(2, 10);
Более подробную информацию по этой теме можно найти здесь: Использование коллекций в Magento