2014-02-18 47 views
5

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

这是我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

更改'实体'为'集合',它将起作用..... –

回答

7

我没有太多的工作与Magento的RESTish API,但

资源的方法尚未实现。

错误字符串在下面不断

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

该常数用于在以下位置

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

因此,要提高关键API错误定义,采取一些教育猜测这里,它看起来像这个错误是抛出时

  1. 你尝试调用创建一个单独的实体

  2. 你尝试调用创建一个集合,而_create_multiCreate方法没有在你的PHP类实现

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

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

_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调用中哪一个会触发您的特定错误(使用一些日志记录),这可能会帮助您解开代码中的错误。

另外,我写了一个article series关于SOAP/XML-RPC API的实现。尽管REST API使用与SOAP/XML-RPC无关的新代码,但该系列仍可能会为您提供关于REST API如何实现的一些信息。

+0

非常感谢您的详细建议。我肯定会研究一下,看看我能否实现它。 – Eddie