I have implemented the Magento 2 Service Contracts, everything is working as expected, I can use my repository's getById
and getList
in Controller but as we know we can use Service Contracts for RestAPI so I have implemented API using webapi.xml but it is not working.
My RepositoryInterface Vendor/Module/Api/TestRepositoryInterface.php
<?php
namespace Vendor\Module\Api;
use \Vendor\Module\Api\Data\TestInterface;
use \Magento\Framework\Api\SearchCriteriaInterface;
interface TestRepositoryInterface
{
/**
* @api
* @param \Vendor\Module\Api\Data\TestInterface $Test
* @return \Vendor\Module\Api\Data\TestInterface
*/
public function save(TestInterface $Test);
/**
* @api
* @param \Vendor\Module\Api\Data\TestInterface $Test
* @return \Vendor\Module\Api\Data\TestInterface
*/
public function delete(TestInterface $Test);
/**
* @api
* @param \Vendor\Module\Api\Data\TestInterface $id
* @return void
*/
public function deleteById($id);
/**
* @api
* @param int $id
* @return \Vendor\Module\Api\Data\TestInterface
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getById($id);
/**
* @api
* @param \Magento\Framework\Api\SearchCriteriaInterface $criteria
* @return \Vendor\Module\Api\Data\TestSearchResultInterface
*/
public function getList(SearchCriteriaInterface $criteria);
}
My Repository Vendor/Module/Model/TestRepository.php
<?php
namespace Vendor\Module\Model;
use \Vendor\Module\Api\Data\TestInterface;
use \Vendor\Module\Model\ResourceModel\Test as ObjectResourceModel;
use \Magento\Framework\Api\SearchCriteriaInterface;
use \Magento\Framework\Exception\CouldNotSaveException;
use \Magento\Framework\Exception\NoSuchEntityException;
use \Magento\Framework\Exception\CouldNotDeleteException;
use \Magento\Framework\Api\SearchResultsInterfaceFactory;
class TestRepository implements \Vendor\Module\Api\TestRepositoryInterface
{
protected $objectFactory;
protected $objectResourceModel;
protected $collectionFactory;
protected $searchResultsFactory;
public function __construct(
\Vendor\Module\Model\TestFactory $objectFactory,
ObjectResourceModel $objectResourceModel,
\Vendor\Module\Model\ResourceModel\Test\CollectionFactory $collectionFactory,
\Magento\Framework\Api\SearchResultsInterfaceFactory $searchResultsFactory
) {
$this->objectFactory = $objectFactory;
$this->objectResourceModel = $objectResourceModel;
$this->collectionFactory = $collectionFactory;
$this->searchResultsFactory = $searchResultsFactory;
}
public function save(TestInterface $object)
{
try {
$this->objectResourceModel->save($object);
} catch (\Exception $e) {
throw new CouldNotSaveException(__($e->getMessage()));
}
return $object;
}
/**
* @inheritdoc
*/
public function getById($id)
{
$object = $this->objectFactory->create();
$this->objectResourceModel->load($object, $id);
if (!$object->getId()) {
throw new NoSuchEntityException(__('Object with id "%1" does not exist.', $id));
}
return $object;
}
public function delete(TestInterface $object)
{
try {
$this->objectResourceModel->delete($object);
} catch (\Exception $exception) {
throw new CouldNotDeleteException(__($exception->getMessage()));
}
return true;
}
public function deleteById($id)
{
return $this->delete($this->getById($id));
}
/**
* @inheritdoc
*/
public function getList(SearchCriteriaInterface $criteria)
{
$searchResults = $this->searchResultsFactory->create();
$searchResults->setSearchCriteria($criteria);
$collection = $this->collectionFactory->create();
foreach ($criteria->getFilterGroups() as $filterGroup) {
$fields = [];
$conditions = [];
foreach ($filterGroup->getFilters() as $filter) {
$condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
$fields[] = $filter->getField();
$conditions[] = [$condition => $filter->getValue()];
}
if ($fields) {
$collection->addFieldToFilter($fields, $conditions);
}
}
$searchResults->setTotalCount($collection->getSize());
$sortOrders = $criteria->getSortOrders();
if ($sortOrders) {
/** @var SortOrder $sortOrder */
foreach ($sortOrders as $sortOrder) {
$collection->addOrder(
$sortOrder->getField(),
($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC'
);
}
}
$collection->setCurPage($criteria->getCurrentPage());
$collection->setPageSize($criteria->getPageSize());
$objects = [];
foreach ($collection as $objectModel) {
$objects[] = $objectModel;
}
$searchResults->setItems($objects);
return $searchResults;
}
}
My DI Vendor/Module/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="Vendor\Module\Api\TestRepositoryInterface" type="Vendor\Module\Model\TestRepository" />
<preference for="Vendor\Module\Api\Data\TestInterface" type="Vendor\Module\Model\Test" />
<preference for="Vendor\Module\Api\Data\TestSearchResultInterface" type="Vendor\Module\Model\TestSearchResult" />
</config>
My WebAPI Vendor/Module/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 method="GET" url="/V1/testing/:id">
<service class="Vendor\Module\Api\TestRepositoryInterface" method="getById"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="GET" url="/V1/testing">
<service class="Vendor\Module\Api\TestRepositoryInterface" method="getList"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
If I access test.local/rest/V1/testing/1 I end up with the following result (nothing),
If I pass non-existent id it throws an exception or if I use die()
in the getById
method it works but somehow not returning actual data.
Whereas if I access test.local/rest/V1/testing it gives me the following result, even though I am using <resource ref="anonymouns"/>
When I created an integration (although it shouldn't be required) to access test.local/rest/V1/testing I encountered the following error.
Above error is obvious because the getList
has mandatory parameter $criteria
but I don't know how to pass because $criteria
param has \Magento\Framework\Api\SearchCriteriaInterface
type.
Remember integration is not working with test.local/rest/V1/testing/1 either, it gives me nothing as above relevant screenshot.
What I am missing? Definitely, I am doing something wrong/silly but what it is? I would like to make it work.
test.local/rest/V1/testing/1 for single record from the database table test.local/rest/V1/testing for all records of the table
I didn't implement other method
under webapi.xml
because I have stuck at the start of the API journey :)
Please HELP (help-flag)
Update
Thanks @raumatbel for the correction, there was a typo in webapi.xml it was anonymouns instead of anonymous, silly isn't it? :)
I am searching using REST endpoints with the following URL
test.local/rest/V1/testing?criteria[filter_groups][0][filters][0][field]=customer_name&criteria[filter_groups][0][filters][0][value]=%na%&criteria[filter_groups][0][filters][0][condition_type]=like
total_count
is 1 but items
node is empty.
No results in either URL test.local/rest/V1/testing/1 or test.local/rest/V1/testing both are empty with no errors.