Extending Magento2 API
Question
I have a very weird problem when trying to extend Magento2 API, I followed all the right steps, however im getting this syntax error when calling http://appfactory.loc/index.php/rest/V1/appfactory/categories
, although im pretty sure it's not a syntax thing, i rechecked the syntax for each file several times.
{
"messages": {
"error": [
{
"code": 500,
"message": "Fatal Error: 'syntax error, unexpected 'interface' (T_INTERFACE)' in 'C:\\stage\\appfactory-magento2\\app\\code\\AppFactory\\Basic\\Api\\CategoryInterface.php' on line 5",
"trace": "Trace is not available."
}
]
}
}
My structure is as follows:
AppFactory/Basic/etc/webapi.xml
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route url="/V1/appfactory/categories" method="GET">
<service class="AppFactory\Basic\Api\CategoryInterface" method="getList"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route url="/V1/appfactory/categories/:id" method="GET">
<service class="AppFactory\Basic\Api\CategoryInterface" method="getById"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
AppFactory/Basic/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="AppFactory\Basic\Api\CategoryInterface"
type="AppFactory\Basic\Model\Api\Category" />
</config>
AppFactory/Basic/Model/Api/Category.php
namespace AppFactory\Basic\Model\Api;
use AppFactory\Basic\Api\CategoryInterface;
class Category implements CategoryInterface{
/**
* Return all the filterable attributes for this category
*
* @return array
*/
public function getById( $id ){return "Test"; }
public function getList() {return "Test2";}
}
AppFactory/Basic/Api/CategoryInterface.php
<?php
namespace AppFactory\Basic\Api;
interface CategoryInterface
{
public function getById( $id );
public function getList();
}
Solution
You need doc blocks for your Interface.
You should use a repository interface which return entities. And this have to be defined by your method doc blocks...
/**
* @api
*/
namespace AppFactory\Basic\Api;
interface CategoryRepositoryInterface {
/**
* @return \AppFactory\Basic\Api\CategoryInterface[]
*/
public function getList();
...
}
This annotations will be parsed by Magento in order to fulfill the API request.
UPDATE 1:
I've reproduce your setup in a CE-2.2-dev Magento instance and got this error message:
{
"message": "Each getter must have description with @return annotation. See AppFactory\\Basic\\Api\\CategoryInterface::getById()",
"trace": "#0 /Volumes/Dev-Part/Workspace/Hackathon/m2-develop/lib/internal/Magento/Framework/Reflection/MethodsMap.php(169): Magento\\Framework\\Reflection\\TypeProcessor->getGetterReturnType(Object(Zend\\Code\\Reflection\\MethodReflection))\n#1 /Volumes/Dev-Part/Workspace/Hackathon/m2
...
}
After changing the interface to the following it does work
<?php
namespace AppFactory\Basic\Api;
/**
* @api
*/
interface CategoryInterface
{
/**
* @param $id
* @return string
*/
public function getById( $id );
/**
* @return array
*/
public function getList();
}
What I mean before is that you should use the "Repository" pattern in order to run close to Magento 2 standards...