Notes
- The Magento 2 Rest Api prefers that you use Interfaces when you want to return complex data with keys/values.
- If you didn't have the
data
key in the response, this would be a little simpler, but I've outlined what you'll need to match the structure you require.
- Magento 2 also prefers to use snake_case keys in it's returned data. If you absolutely need camelCase, this link might point you in the right direction, but I'm pretty sure it will have unintended consequences considering the frontend of Magento also uses the rest api and is probably expecting data in snake_case form: Magento 2 Github Issue
Summary
- Create a wrapping/container interface to have the
data
key. I've named it RemainingDataContainerInterface
, but you could name it whatever you want.
- Create an interface to describe the shape of your "remaining data" DTO (Data Transfer Object). I've named it
RemainingDataInterface
, but you can call it whatever you want.
- Create the implementations of the new interfaces. These usually reside in your modules Model folder
- Declare the DI (Dependency Injection) preferences for the interfaces to map them to your implementations
- Update your
OrdersRepositoryInterface::get()
php doc block to specify that it will return a \Lovat\Api\Api\Data\RemainingDataContainerInterface
. It is important that the return arg is the FQCN (Fully Qualified Class Name) for Magento to know which interface you are talking about
- In your
OrdersRepository
class, inject factories of the new interfaces
- In your
OrdersRepository::get()
method, create instances from the factories, populate their data, and return the instance of the RemainingDataContainerInterface
Module Structure
app/code/Lovat
└── Api
├── Api
│ ├── Data
│ │ ├── RemainingDataContainerInterface.php
│ │ └── RemainingDataInterface.php
│ └── OrdersRepositoryInterface.php
├── composer.json
├── etc
│ ├── di.xml
│ ├── module.xml
│ └── webapi.xml
├── Model
│ ├── OrdersRepository.php
│ ├── RemainingDataContainer.php
│ └── RemainingData.php
└── registration.php
Files
app/code/Lovat/Api/Api/Data/RemainingDataContainerInterface.php
<?php
namespace Lovat\Api\Api\Data;
interface RemainingDataContainerInterface
{
const DATA = 'data';
/**
* @return \Lovat\Api\Api\Data\RemainingDataInterface
*/
public function getData();
/**
* @param \Lovat\Api\Api\Data\RemainingDataInterface $data
* @return $this
*/
public function setData(RemainingDataInterface $data);
}
app/code/Lovat/Api/Api/Data/RemainingDataInterface.php
<?php
namespace Lovat\Api\Api\Data;
interface RemainingDataInterface
{
const REMAINING_DATA = 'remaining_data';
const COUNT = 'count';
const LIMIT = 'limit';
const OFFSET = 'offset';
/**
* @return int
*/
public function getRemainingData();
/**
* @return int
*/
public function getCount();
/**
* @return int
*/
public function getLimit();
/**
* @return int
*/
public function getOffset();
/**
* @param int $remainingData
* @return $this
*/
public function setRemainingData($remainingData);
/**
* @param int $count
* @return $this
*/
public function setCount($count);
/**
* @param int $limit
* @return $this
*/
public function setLimit($limit);
/**
* @param int $offset
* @return $this
*/
public function setOffset($offset);
}
app/code/Lovat/Api/Api/OrdersRepositoryInterface.php
<?php
namespace Lovat\Api\Api;
interface OrdersRepositoryInterface
{
/**
* @param string $from
* @param string $to
* @param int $p
* @return \Lovat\Api\Api\Data\RemainingDataContainerInterface
*/
public function get(string $from, string $to, int $p = 1);
}
app/code/Lovat/Api/Model/OrdersRepository.php
<?php
namespace Lovat\Api\Model;
use Lovat\Api\Api\Data\RemainingDataContainerInterface;
use Lovat\Api\Api\Data\RemainingDataContainerInterfaceFactory;
use Lovat\Api\Api\Data\RemainingDataInterface;
use Lovat\Api\Api\Data\RemainingDataInterfaceFactory;
use Lovat\Api\Api\OrdersRepositoryInterface;
class OrdersRepository implements OrdersRepositoryInterface
{
/**
* @var RemainingDataContainerInterfaceFactory
*/
protected $remainingDataContainerFactory;
/**
* @var RemainingDataInterfaceFactory
*/
protected $remainingDataFactory;
/**
* OrdersRepository constructor.
* @param RemainingDataContainerInterfaceFactory $remainingDataContainerFactory
* @param RemainingDataInterfaceFactory $remainingDataFactory
*/
public function __construct(
RemainingDataContainerInterfaceFactory $remainingDataContainerFactory,
RemainingDataInterfaceFactory $remainingDataFactory
) {
$this->remainingDataContainerFactory = $remainingDataContainerFactory;
$this->remainingDataFactory = $remainingDataFactory;
}
/**
* @inheritDoc
*/
public function get(string $from, string $to, int $p = 1)
{
/** @var RemainingDataContainerInterface $remainingDataContainer */
$remainingDataContainer = $this->remainingDataContainerFactory->create();
/** @var RemainingDataInterface $remainingData */
$remainingData = $this->remainingDataFactory->create();
$remainingData->setRemainingData(0)
->setCount(2)
->setLimit(5000)
->setOffset(22);
$remainingDataContainer->setData($remainingData);
return $remainingDataContainer;
}
}
app/code/Lovat/Api/Model/RemainingData.php
<?php
namespace Lovat\Api\Model;
use Lovat\Api\Api\Data\RemainingDataInterface;
use Magento\Framework\DataObject;
class RemainingData extends DataObject implements RemainingDataInterface
{
/**
* @inheritDoc
*/
public function getRemainingData()
{
return $this->getData(self::REMAINING_DATA);
}
/**
* @inheritDoc
*/
public function getCount()
{
return $this->getData(self::COUNT);
}
/**
* @inheritDoc
*/
public function getLimit()
{
return $this->getData(self::LIMIT);
}
/**
* @inheritDoc
*/
public function getOffset()
{
return $this->getData(self::OFFSET);
}
/**
* @inheritDoc
*/
public function setRemainingData($remainingData)
{
return $this->setData(self::REMAINING_DATA, $remainingData);
}
/**
* @inheritDoc
*/
public function setCount($count)
{
return $this->setData(self::COUNT, $count);
}
/**
* @inheritDoc
*/
public function setLimit($limit)
{
return $this->setData(self::LIMIT, $limit);
}
/**
* @inheritDoc
*/
public function setOffset($offset)
{
return $this->setData(self::OFFSET, $offset);
}
}
app/code/Lovat/Api/Model/RemainingDataContainer.php
<?php
namespace Lovat\Api\Model;
use Lovat\Api\Api\Data\RemainingDataContainerInterface;
use Lovat\Api\Api\Data\RemainingDataInterface;
class RemainingDataContainer implements RemainingDataContainerInterface
{
/**
* @var \Lovat\Api\Api\Data\RemainingDataInterface
*/
protected $data;
/**
* @inheritDoc
*/
public function getData()
{
return $this->data;
}
/**
* @inheritDoc
*/
public function setData(RemainingDataInterface $data)
{
$this->data = $data;
return $this;
}
}
app/code/Lovat/Api/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="Lovat\Api\Api\Data\RemainingDataContainerInterface" type="Lovat\Api\Model\RemainingDataContainer"/>
<preference for="Lovat\Api\Api\Data\RemainingDataInterface" type="Lovat\Api\Model\RemainingData"/>
<preference for="Lovat\Api\Api\OrdersRepositoryInterface" type="Lovat\Api\Model\OrdersRepository"/>
</config>
Example Api Response
Link to Download Code Mentioned Above
Dropbox Download Link