Question

I set up a working custom route for Magento's REST Api.

It works fine for GET requests, as the _retrieve() function of the corresponding V1.php class is being called as expected and returns the data. But now I'm trying to handle POST requests and that's when Magento is behaving weird:

  • When you want to post data you have to define the data as a collection instead of an entity in etc/api2.xml like this: <action_type>collection</action_type>. Otherwise Magento will throw this error in Mage_Api2_Model_Resource (line 207):
// Creation of objects is possible only when working with collection
$this->_critical(self::RESOURCE_METHOD_NOT_IMPLEMENTED);

So when I define the action_type as collection, then the _multiCreate() function of the corresponding V1.php is being called as expected.

  • However Magento now doesn't let me return any data. I want to return this array in JSON format:

    $response = array("success"=>true, "error"=>"", "model"=>array(1,2,3));

'success', 'error' and 'model' are defined as attributes in the api2.xml and should therefore be available. But when I return $response, the response is empty with Status 207 ... Hmmm! Now since it has action_type collection, I have also tried to return the $response wrapped inside another array, but without success.

In my final tryouts I figured out that by setting data with the method $this->getResponse()->addMessage(....) I am able to retrieve data, but I don't think that this is the correct way as it is thought to be for success/error/warning message types and it doesn't fit my data type requirements.

Last but not least I also tried to return data by using the $this->getResponse()->setBody($result) and $this->getResponse()->setRawBody($result) methods, but again - no success:

So Magento experts - What is the correct way to retrieve data from a POST request to the REST Api? I desperately need your help!!

Here's my api2.xml:

<customer_login translate="title" module="Test_Restapi">
    <group>restapi</group>
    <model>restapi/api2_customer_login</model>
    <title>Blablabla</title>
    <sort_order>10</sort_order>
    <privileges>
        <customer>
            <create>1</create>
            <update>1</update>
            <retrieve>1</retrieve>
        </customer>
        <guest>
            <create>1</create>
            <update>1</update>
            <retrieve>1</retrieve>
        </guest>
    </privileges>
    <attributes>
        <success>Success</success>
        <error>Error</error>
        <model>Model</model>
    </attributes>
    <routes>
        <route_collection>
            <route>/restapi/customer/login</route>
            <action_type>collection</action_type>
        </route_collection>
    </routes>
    <versions>1</versions>
</customer_login>
Was it helpful?

Solution

If you take a look at class Mage_Api2_Model_Resource which should be extended by your class, you can find function _render().

By examining dispach() function of this class, you can see, that _render() function is called by retrieve operations. So you can use this function at the end of your action like so $this->_render($data).

This function is not used by create operations, which only set Location header to newly created resource url.

To take an advantage of attribute filtering, use $this->getFilter()->out($data) before $this->_render($data)

Mage_Api2_Model_Resource::dispatch() can answer a lot of questions regarding magento REST!

OTHER TIPS

I managed to retrieve data from the _createMulti() function by following @raivis.krumins suggestions. Inside the dispatch() function of the Mage_Api2_Model_Resource class I added these 3 lines after line 228 at the end of the if statement where the location header is being set:

$retrievedData = $this->_createMulti($filteredData);
$returnData  = $this->getFilter()->out($retrievedData);
$this->_render($returnData);

The first line retrieves the result from the function, the second line filters out unwanted attributes (the ones not set in api2.xml) and finally the third line returns the data in the response.

Please note that these changes should always be made in a custom module. Never change a core class!

Just before reruns in your custom module function set

$this->getResponse()->appendBody(json_encode($response));

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top