2014-02-18 46 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