===== Create your own API =====
... api for customer module, that operates with basic customer info (firstname, lastname, email ...).
==== 1. Describe API Resource in api.xml ====
Create api.xml in customer module /etc folder with this contents:
We have to implement create, list, info, update and remove methods for customer resource.
Lets add it to resources.
....
Customer Resource
Retrive customers
Create customer
Retrieve customer data
Update customer data
Delete customer
....
Our resource will return some faults, let's list them in the config:
....
....
100 code>
Invalid customer data. Details in error message.
101 code>
Invalid filters specified. Details in error message.
102 code>
Customer doesn't exist.
103 code>
Customer was not deleted. Details in error message.
....
==== 2. Describe ACL For API Resource ====
In order to prevent unathorized access to our custom API we have to define the ACL resources that can be restricted.
....
Customers
View All
Create
Get Info
Update
Delete
We also have to map ACL resources to API resource methods:
Customer Resource
customer
Retrive customers
customer/list
Create customer
customer/create
Retrieve customer data
customer/info
Update customer data
customer/update
Delete customer
customer/delete
....
....
==== 3. Creating API Resource Model ====
Let's create Mage_Customer_Model_Api that extends Mage_Api_Model_Resource_Abstract
class Mage_Customer_Model_Api extends Mage_Api_Model_Resource_Abstract
{
public function create($customerData)
{
}
public function info($customerId)
{
}
public function items($filters)
{
}
public function update($customerId, $customerData)
{
}
public function delete($customerId)
{
}
}
We cannot create method "list" because it's a PHP keyword, so we will add the following to api.xml:
customer/api
Customer Resource
customer
Retrive customers
items
customer/list
....
....
....
And now will add some simple functionality to our resource model.
Create Customer:
public function create($customerData)
{
try {
$customer = Mage::getModel('customer/customer')
->setData($customerData)
->save();
} catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
// We cannot know all the possible exceptions,
// so let's try to catch the ones that extend Mage_Core_Exception
} catch (Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
return $customer->getId();
}
Customer Info:
public function info($customerId)
{
$customer = Mage::getModel('customer/customer')->load($customerId);
if (!$customer->getId()) {
$this->_fault('not_exists');
// If customer not found.
}
return $customer->toArray();
// We can use only simple PHP data types in webservices.
}
Customers List with filtering.
public function items($filters)
{
$collection = Mage::getModel('customer/customer')->getCollection()
->addAttributeToSelect('*');
if (is_array($filters)) {
try {
foreach ($filters as $field => $value) {
$collection->addFieldToFilter($field, $value);
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
// If we are adding filter on non-existent attribute
}
}
$result = array();
foreach ($collection as $customer) {
$result[] = $customer->toArray();
}
return $result;
}
Customer Update:
public function update($customerId, $customerData)
{
$customer = Mage::getModel('customer/customer')->load($customerId);
if (!$customer->getId()) {
$this->_fault('not_exists');
// No customer found
}
$customer->addData($customerData)->save();
return true;
}
Customer Delete:
public function delete($customerId)
{
$customer = Mage::getModel('customer/customer')->load($customerId);
if (!$customer->getId()) {
$this->_fault('not_exists');
// No customer found
}
try {
$customer->delete();
} catch (Mage_Core_Exception $e) {
$this->_fault('not_deleted', $e->getMessage());
// Some errors while deleting.
}
return true;
}
===== Creating custom adapter for api =====
In order to create custom webservice adapter we should implement Mage_Api_Model_Server_Adapter_Interface
interface Mage_Api_Model_Server_Adapter_Interface
{
/**
* Set handler class name for webservice
*
* @param string $handler
* @return Mage_Api_Model_Server_Adapter_Interface
*/
function setHandler($handler);
/**
* Retrive handler class name for webservice
*
* @return string
*/
function getHandler();
/**
* Set webservice api controller
*
* @param Mage_Api_Controller_Action $controller
* @return Mage_Api_Model_Server_Adapter_Interface
*/
function setController(Mage_Api_Controller_Action $controller);
/**
* Retrive webservice api controller
*
* @return Mage_Api_Controller_Action
*/
function getController();
/**
* Run webservice
*
* @return Mage_Api_Model_Server_Adapter_Interface
*/
function run();
/**
* Dispatch webservice fault
*
* @param int $code
* @param string $message
*/
function fault($code, $message);
} // Class Mage_Api_Model_Server_Adapter_Interface End
XmlRpc Adapter example:
class Mage_Api_Model_Server_Adapter_Customxmlrpc
extends Varien_Object
implements Mage_Api_Model_Server_Adapter_Interface
{
/**
* XmlRpc Server
*
* @var Zend_XmlRpc_Server
*/
protected $_xmlRpc = null;
/**
* Set handler class name for webservice
*
* @param string $handler
* @return Mage_Api_Model_Server_Adapter_Xmlrpc
*/
public function setHandler($handler)
{
$this->setData('handler', $handler);
return $this;
}
/**
* Retrive handler class name for webservice
*
* @return string
*/
public function getHandler()
{
return $this->getData('handler');
}
/**
* Set webservice api controller
*
* @param Mage_Api_Controller_Action $controller
* @return Mage_Api_Model_Server_Adapter_Xmlrpc
*/
public function setController(Mage_Api_Controller_Action $controller)
{
$this->setData('controller', $controller);
return $this;
}
/**
* Retrive webservice api controller
*
* @return Mage_Api_Controller_Action
*/
public function getController()
{
return $this->getData('controller');
}
/**
* Run webservice
*
* @param Mage_Api_Controller_Action $controller
* @return Mage_Api_Model_Server_Adapter_Xmlrpc
*/
public function run()
{
$this->_xmlRpc = new Zend_XmlRpc_Server();
$this->_xmlRpc->setClass($this->getHandler());
$this->getController()->getResponse()
->setHeader('Content-Type', 'text/xml')
->setBody($this->_xmlRpc->handle());
return $this;
}
/**
* Dispatch webservice fault
*
* @param int $code
* @param string $message
*/
public function fault($code, $message)
{
throw new Zend_XmlRpc_Server_Exception($message, $code);
}
} // Class Mage_Api_Model_Server_Adapter_Customxmlrpc End
"setHandler", "getHandler", "setController" and "getController" methods have simple implementation that uses Varien_Object getData/setData methods.
"run" an "fault" have native implementation for XmlRpc webservice.
Method "run" defines webservice logic in this adapter for creating XmlRpc server to handle XmlRpc requests.
public function run()
{
$this->_xmlRpc = new Zend_XmlRpc_Server();
$this->_xmlRpc->setClass($this->getHandler());
$this->getController()->getResponse()
->setHeader('Content-Type', 'text/xml')
->setBody($this->_xmlRpc->handle());
return $this;
}
Method "fault" allows us to send fault exceptions for XmlRpc service while handling request.
public function fault($code, $message)
{
throw new Zend_XmlRpc_Server_Exception($message, $code);
}