我一直在尝试扩展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中特定标记的含义以及方法映射应该如何完成。
提前致谢。
答案 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);
}
}
所以,在这里进行一些教育猜测,看起来像
时会抛出这个错误您尝试在单个实体上调用create
您尝试在集合上调用create,并且您的PHP类尚未实现_create
或_multiCreate
方法
您尝试调用的方法不是规范的CRUD方法之一(默认情况下)
或者,如果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
的调用中的哪一个会触发您的特定错误(使用一些日志记录),这可能会帮助您解决代码的错误。
另外,我在SOAP / XML-RPC API的实现上写了article series。虽然REST API使用与SOAP / XML-RPC无关的新代码,但该系列仍然可以为您提供有关如何实现REST API的一些见解。