Magento REST API创建方法 - 未实现资源方法

时间:2014-02-18 01:51:14

标签: php magento rest

我一直在尝试扩展magento的REST API以添加可配置产品,但我遇到错误405 - 资源方法未实现。

这是我的api.xml:

<?xml version="1.0"?>
<config>
    <api>
        <resources>
            <extapi_catalog translate="title" module="extapi">
                <model>extapi/catalog_api2</model>
                <title>Extapi Catalog API</title>
                <acl>extapi/product</acl>
                <methods>
                    <list translate="title" module="extapi">
                        <title>Retrieve Product Count</title>
                        <method>count</method>
                        <acl>extapi/product/info</acl>
                    </list>
                    <create translate="title" module="extapi">
                        <title>Create products</title>
                        <acl>extapi/product/create</acl>
                    </create>
                    <update translate="title" module="extapi">
                        <title>Update products</title>
                        <method>update</method>
                        <acl>extapi/product/update</acl>
                    </update>
                    <delete translate="title" module="extapi">
                        <title>Delete products</title>
                        <method>delete</method>
                        <acl>extapi/product/delete</acl>
                    </delete>
                </methods>
                <faults module="extapi">
                    <data_invalid>
                        <code>100</code>
                        <message>Invalid Request. Details in error message.</message>
                    </data_invalid>
                    <filters_invalid>
                        <code>101</code>
                        <message>Invalid filters specified. Details in error message.</message>
                    </filters_invalid>
                    <not_exists>
                        <code>102</code>
                        <message>No products.</message>
                    </not_exists>
                    <not_deleted>
                        <code>103</code>
                        <message>Product not deleted. Details in error message.</message>
                    </not_deleted>
                </faults>
            </extapi_catalog>
        </resources>
        <v2>
            <resources_function_prefix>
                <extapi_catalog>extapi_catalog</extapi_catalog>
            </resources_function_prefix>
        </v2>

        <acl>
            <resources>
                <extapi_catalog translate="title" module="extapi">
                    <title>Catalog</title>
                    <sort_order>3</sort_order>
                    <info translate="title" module="extapi">
                        <title>Retrieve product count</title>
                    </info>
                    <create translate="title" module="extapi">
                        <title>Create product count</title>
                    </create>
                    <update translate="title" module="extapi">
                        <title>Update product count</title>
                    </update>
                    <delete translate="title" module="extapi">
                        <title>Delete product count</title>
                    </delete>
                </extapi_catalog>
            </resources>
        </acl>
    </api>
</config>

这是我的api2.xml:

<?xml version="1.0"?>
<config>
    <api2>
        <resource_groups>
            <extapi translate="title" module="api2">
                <title>Magepim API calls</title>
                <sort_order>30</sort_order>
                <children>
                    <extapi_product translate="title" module="api2">
                        <title>Product</title>
                        <sort_order>50</sort_order>
                    </extapi_product>
                </children>
            </extapi>
        </resource_groups>
        <resources>
            <extapiproducts translate="title" module="api2">
                <group>extapi_product</group>
                <model>extapi/catalog_api2_product</model>
                <working_model>extapi/catalog_api2_product</working_model>
                <title>Catalog Product</title>
                <sort_order>10</sort_order>
                <privileges>
                    <admin>
                        <create>1</create>
                        <retrieve>1</retrieve>
                        <update>1</update>
                        <delete>1</delete>
                    </admin>
                </privileges>
                <attributes translate="product_count" module="api2">
                    <product_count>Product Count</product_count>
                    <catalog_size>Product Count</catalog_size>
                </attributes>
                <entity_only_attributes>
                    <catalog>
                        <read>
                            <has_custom_options>1</has_custom_options>
                            <tier_price>1</tier_price>
                            <total_reviews_count>1</total_reviews_count>
                            <url>1</url>
                            <buy_now_url>1</buy_now_url>
                            <has_custom_options>1</has_custom_options>
                            <is_in_stock>1</is_in_stock>

                        </read>
                    </catalog>
                    </entity_only_attributes>
                <exclude_attributes>
                    <catalog>
                        <read>
                            <attribute_set_id>1</attribute_set_id>
                            <stock_data>1/</stock_data>
                            <use_config_gift_message_available>1</use_config_gift_message_available>
                            <use_config_gift_wrapping_available>1</use_config_gift_wrapping_available>
                            <url_key_create_redirect>1</url_key_create_redirect>

                        </read>
                    </catalog>
                    <admin>
                        <read>
                            <product_count>1</product_count>
                        </read>
                    </admin>
                </exclude_attributes>
                <routes>
                    <route_entity_count>
                        <route>/magepim/products</route>
                        <action_type>entity</action_type>
                    </route_entity_count>
                </routes>
                <versions>1</versions>
            </extapiproducts>
        </resources>
    </api2>
</config>

这是我的V1.php:

<?php

/**
 * Override for Magento's Catalog REST API
 */
class Magepim_Extapi_Model_Catalog_Api2_Product_Rest_Admin_V1 extends Mage_Catalog_Model_Api2_Product_Rest {

    /**
     * Retrieves the catalog collection and returns it's size
     *
     * @return int
     */

    protected function _retrieve()
    {
        /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */
        $collection = Mage::getResourceModel('catalog/product_collection');
        $store = $this->_getStore();
        $collection->setStoreId($store->getId());
        $collection->addAttributeToSelect(array_keys(
                $this->getAvailableAttributes($this->getUserType(), Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ)
        ));
        $this->_applyCategoryFilter($collection);
        $this->_applyCollectionModifiers($collection);
        $products = $collection->load()->toArray();
        $size = $collection->getSize();
        $productCount = new stdClass();
        $productCount->catalog_size=$size;
        //return $size;
        return json_encode($productCount);
    }

    protected function _create($data)
    {
        /* @var $validator Mage_Catalog_Model_Api2_Product_Validator_Product */
        $validator = Mage::getModel('catalog/api2_product_validator_product', array(
            'operation' => self::OPERATION_CREATE
        ));

        if (!$validator->isValidData($data)) {
            foreach ($validator->getErrors() as $error) {
                $this->_error($error, Mage_Api2_Model_Server::HTTP_BAD_REQUEST);
            }
            $this->_critical(self::RESOURCE_DATA_PRE_VALIDATION_ERROR);
        }

        $type = $data['type_id'];
        if ($type !== 'simple') {
            $this->_critical("Creation of products with type '$type' is not implemented",
                Mage_Api2_Model_Server::HTTP_METHOD_NOT_ALLOWED);
        }
        $set = $data['attribute_set_id'];
        $sku = $data['sku'];

        /** @var $product Mage_Catalog_Model_Product */
        $product = Mage::getModel('catalog/product')
            ->setStoreId(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID)
            ->setAttributeSetId($set)
            ->setTypeId($type)
            ->setSku($sku);

        foreach ($product->getMediaAttributes() as $mediaAttribute) {
            $mediaAttrCode = $mediaAttribute->getAttributeCode();
            $product->setData($mediaAttrCode, 'no_selection');
        }

        $this->_prepareDataForSave($product, $data);
        try {
            $product->validate();
            $product->save();
            $this->_multicall($product->getId());
        } catch (Mage_Eav_Model_Entity_Attribute_Exception $e) {
            $this->_critical(sprintf('Invalid attribute "%s": %s', $e->getAttributeCode(), $e->getMessage()),
                Mage_Api2_Model_Server::HTTP_BAD_REQUEST);
        } catch (Mage_Core_Exception $e) {
            $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR);
        } catch (Exception $e) {
            $this->_critical(self::RESOURCE_UNKNOWN_ERROR);
        }

        return $this->_getLocation($product);
    }

    protected function _multicreate($data)
    {
        $this->getResponse ()->addMessage ( "", 0, array (
            'result' => "created" 
        ), Mage_Api2_Model_Response::MESSAGE_TYPE_SUCCESS );
        $this->getResponse ()->setRawHeader ( '"Content-Type" = "application/json"' );
        $base_url = Mage::getBaseUrl ( Mage_Core_Model_Store::URL_TYPE_WEB );
        $base_url = substr ( $base_url, 0, strlen ( $base_url ) - 1 );
        return $base_url . $this->_getLocation ( $order );
    }

    protected function _update(array $data)
    {
        return json_encode($productCount);
    }

    protected function _delete()
    {
        $this->getResponse ()->addMessage ( "", 0, array (
            'result' => "deleted" 
        ), Mage_Api2_Model_Response::MESSAGE_TYPE_SUCCESS );
        return json_encode(array("result","_delete"));
    }
}

在此阶段,_retrieve()是唯一正常工作的方法。 _delete()似乎能够接收方法调用并返回代码200. _update()似乎也正确接收方法调用,即使它返回编码错误。

我的主要问题是_create(),它根本没有被调用。即使我删除了方法中的所有语句(从/app/Mage/Model/Api2/Product/Rest/AdminV1.php复制),同样的问题仍然存在。

有人可以给我一些建议吗?此外,是否有任何可用于扩展REST API(而非Core API)的文档?我在网上找到了一些教程(我的代码扩展到了其中一个教程),但是它们都没有指定api.xml / api2.xml中特定标记的含义以及方法映射应该如何完成。

提前致谢。

1 个答案:

答案 0 :(得分:7)

我没有使用Magento的RESTish API,但

  

资源方法尚未实施。

错误字符串在以下常量

中定义
#File: app/code/core/Mage/Api2/Model/Resource.php
const RESOURCE_METHOD_NOT_IMPLEMENTED = 'Resource method not implemented yet.';

此常量用于在以下位置引发关键API错误

#File: app/code/core/Mage/Api2/Model/Resource.php
public function dispatch()
{
    switch ($this->getActionType() . $this->getOperation()) {    
        case self::ACTION_TYPE_ENTITY . self::OPERATION_CREATE:
            // Creation of objects is possible only when working with collection
            $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
            break;
        case self::ACTION_TYPE_COLLECTION . self::OPERATION_CREATE:
            // If no of the methods(multi or single) is implemented, request body is not checked
            if (!$this->_checkMethodExist('_create') && !$this->_checkMethodExist('_multiCreate')) {
                $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
            }
        ...
        default:
            $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
    }
}

...

protected function _errorIfMethodNotExist($methodName)
{
    if (!$this->_checkMethodExist($methodName)) {
        $this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);
    }
}

所以,在这里进行一些教育猜测,看起来像

时会抛出这个错误
  1. 您尝试在单个实体上调用create

  2. 您尝试在集合上调用create,并且您的PHP类尚未实现_create_multiCreate方法

  3. 您尝试调用的方法不是规范的CRUD方法之一(默认情况下)

  4. 或者,如果Magento系统代码调用受保护的_errorIfMethodNotExist错误。

  5. _errorIfMethodNotExist使用了很多,但与_create次调用有关,这里使用的是

    #File: app/code/core/Mage/Api2/Model/Resource.php
    // The create action has the dynamic type which depends on data in the request body
    if ($this->getRequest()->isAssocArrayInRequestBody()) {
        $this->_errorIfMethodNotExist('_create');
        $filteredData = $this->getFilter()->in($requestData);
        if (empty($filteredData)) {
            $this->_critical(self::RESOURCE_REQUEST_DATA_INVALID);
        }
        $newItemLocation = $this->_create($filteredData);
        $this->getResponse()->setHeader('Location', $newItemLocation);
    

    我不太清楚这是什么意思。也许上面的评论对你有意义(如果你使用REST API)。

    无论如何,我会弄清楚这些对_critical的调用中的哪一个会触发您的特定错误(使用一些日志记录),这可能会帮助您解决代码的错误。

    另外,我在SOAP / XML-RPC API的实现上写了article series。虽然REST API使用与SOAP / XML-RPC无关的新代码,但该系列仍然可以为您提供有关如何实现REST API的一些见解。