Categories


Archives


Recent Posts


Categories


The Magento API

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

I’ve been wanting to write about the Magento API for a long time, but it’s one of those slippery topics that has no clean entry point. It’s easy to talk about small slices of the API, or provide tricks for using the API methods natively, but teaching someone how to figure these things out for themselves is another matter. The code patterns used to implement The Magento API will be foreign to most LAMP stack developers, and it’s impossible to discuss the reasoning behind one part of the system without understanding its place in the whole.

All of which means it’s time for another extend dive into Magento’s core.

We’re going to start simple with the 10,000 foot overview and a few definitions. Some of this might not make sense or seem immediately applicable. However, by the time this series is over you’ll be able to understand all the concepts below, and those same concepts will help you make sense of the twists and turns of Magento’s API implementation.

Architecture of an API

The basic architecture of the Magento API can be described as follows

An HTTP request is made to a URL and Magento’s standard routing system sends that request to a controller action in the Mage_Api module. This controller action instantiates a Magento API server object, initializes that object with the API type (soap, XML-RPC, etc.), and then calls the server object’s run method.

The API server is responsible for handling the API request, and directly setting the output on the response object. There’s no layout XML here, no loadLayout/renderLayout methods need to be called.

This API object is a Magento model with the class alias api/server, making it a Mage_Api_Model_Server object. There’s also an intended architecture the server object uses to achieve its goals. That architecture can be described as follows

On initialization the API server object will, based on the passed in paramaters, examine the Magento configuration to determine which API adapter object and API handler object should be instantiated. A handler object is subservient to an adapter object. Upon having its run method called, the API server object calls the run method on the adapter object, making the adapter object ultimately responsible for fulfilling the API request.

The relationship between adapters and handlers can be tricky to understand, and reveals a few of the of the assumptions made by the team that worked on the Magento API. Defined without context, that relationships can be described with the following

The adapter object is responsible for including and instantiating the API libraries and objects, while the handler is responsible for translating an API function call to the correct Magento API resource class and method

To understand this definition, you’ll need a little background on the history of SOAP and XML-RPC style APIs

Non-RESTful APIs

If you’re a web developer, most of the APIs you’ve encountered are likely to be RESTful. That is, you make a request to a specific URL, maybe with some POST variables, or maybe setting a request type like POST/PUT. This API will return something like JSON or XML, which your program can use as it sees fit.

When a web developer gets interested in developing an API of their own, they’ll tend to think of it in terms of

OK, I need to write some code that intercepts a URL request, and then write some more code that does the work of the request

There’s nothing wrong with this description of an API, but it does miss something the creators of XML-RPC and SOAP wanted to accomplish. These API creators started with a different assumed brief

OK, we need to find a way to call a method defined in a program on Computer B from a program defined on Computer A

You can probably see how the web developer’s version of a RESTful API fits within this second definition, but I hope you can also see how these slightly different points of view created a bias in how the APIs were implemented.

Most language/platform libraries for SOAP and XML-RPC will automatically handle creating the correct request processing and response sending for a particular API syntax. For example, consider the basic code sample for the PHP SoapServer class (from the PHP manual)

$server = new SoapServer(null, array('uri' => "http://test-uri/"));
$server->addFunction("test");
$server->addFunction("someOtherFunction");
$server->handle();

What this code is saying is (in grossly over simplified terms)

  1. Start a SOAP Server

  2. Allow SOAP clients to call the currently defined PHP functions test and someOtherFunction

  3. “Handle” the request, meaning examine the incoming request for the standard SOAP XML, and if that SOAP XML says “call test or someOtherFunction” then call the functions and return a result.

Most XML-RPC libraries work on a similar principle, and as you’ll soon realize, the Magento API architecture assumes all potential API types will have a similar interface.

Magento API Adapters and Handlers

The adapter object’s job is to instantiate API handling classes like the aforementioned SoapServer and ensure any output is sent to the Magento response object rather than directly to the main PHP output buffer.

The handler object’s job is to expose methods to the API library instantiated by the adapter object. The SoapServer example above exposes the test and someOtherFunction functions. Most of these API implementations also allow you to say something like

Expose (i.e. addFunction, as above) all the public methods on this particular object to the API

That’s what a handler object is for. For example, the default handler class (used for the the v1 SOAP API and the XML-RPC API) is a Magento model with the class alias api/server_handler, which translates to the class Mage_Api_Model_Server_Handler. If we take a look at this class

#File: app/code/core/Mage/Api/Model/Server/Handler.php
class Mage_Api_Model_Server_Handler extends Mage_Api_Model_Server_Handler_Abstract
{

}

we see it’s empty, but if we look at its Mage_Api_Model_Server_Handler_Abstract parent class

#File: app/code/core/Mage/Api/Model/Server/Handler/Abstract.php
abstract class Mage_Api_Model_Server_Handler_Abstract
{
    public function startSession()
    {
        //...
    }

    public function endSession($sessionId)
    {
        //...
    }

    public function login($username, $apiKey)
    {        
        //...
    }

    public function call($sessionId, $apiPath, $args = array())
    {
        //...
    }

    public function multiCall($sessionId, array $calls = array(), $options = array())
    {
        //...
    }

    public function resources($sessionId)
    {        
        //...
    }

    public function globalFaults($sessionId)
    {
        //...
    }

    public function resourceFaults($sessionId, $resourceName)
    {
        //...
    }
}

we can see definitions for the eight methods exposed to API clients. The most important method of the handler is the call method. This is sometimes refereed to as a keyhole method, and is the method you call from the client side to access a particular resource and method of the Magento API. This call method is where the handler object translates that resource and method name into a call to native PHP/Magento code.

Wrap Up

The implementation of the Magento API uses programming patterns and concepts that differ from what a day-to-day LAMP stack programmer is used to. This makes it difficult for a developer to debug their API based programs.

Additionally, any SOAP traditionalists are left confused and frustrated by the keyhole call method at the center of the API implementation, since most traditional SOAP tools assume that using an API method to create a product means using a method directly exposed via the API.

As we continue this series and dive deeper into the API implementation we’ll be theorizing as to why the Magento team made some of these choices, as well as cover how they later leveraged these built in abstractions to provide those SOAP traditionalists with an experience closer to what they were expecting. If this articles is the 10,000 foot view, then next week we’ll be getting down in the mud and lost in the details of how Magento’s code implements the architecture described above.

Originally published April 3, 2012
Series Navigation<< Scrubbing Bubbles for Magento’s SOAPMagento API Adapters and Handlers >>