Introduction to XML-RPC Requests With PHP

First let me say this: the few long-time readers I have (thanks!) know that Sunday is when I write about my Book of the Week. However, the book I am reading now is long, as was the last one I read. So I am adopting a new practice: if I decide to read a book over five-hundred pages in length then I am giving myself two weeks to read it instead of one. So I will be writing about that book next Sunday.

Therefore, instead of the usual Sunday post, today I am writing an introduction for a fellow programmer on dealing with XML-RPC using PHP. I am focusing specifically on programming a client, something that communicates with a server that provides services via XML-RPC. I will not be talking about any server-side implementation.

Practical Approach

I try as much as possible to not spend my programming time reinventing the wheel, and try to persuade others to do the same. So realistically I would recommend that PHP developers use an existing library such as XML-RPC for PHP. But for the sake of explaining the underlying process I am not going to use such a library in this article. This bare-bones approach is for educational purposes only. I strongly recommend using existing libraries whenever you can for non-trivial software.

A Short Overview of XML-RPC

XML-RPC is a way to make a remote procedure call. Basically it allows us to ask another program, in this case a server, to execute some procedure on our behalf. For example, in this article I will be using XML-RPC to give a server a number and ask it to tell me the name of the associated state in the United States (i.e. an example from Wikipedia).

It is obvious from the name, but we write our requests using XML. And servers also send their response in the same format. These requests and responses go back and forth over HTTP, the protocol of communication for XML-RPC. That provides a nice benefit; we almost always use PHP for writing web applications and so the standard library already has all the tools we need to ‘speak’ HTTP.

So that is the gist of XML-RPC: regular HTTP requests and responses that use a language in XML for their content.

A Simple Example

Here is one way we can create and send an XML-RPC request.

/**
 * This is the URL of the server that provides services via XML-RPC,
 * so this is where we want to send our requests.
 */
const SERVER_URL = "http://phpxmlrpc.sourceforge.net/server.php";

/**
 * When we send the XML-RPC request we will have to provide a
 * User-Agent name:
 * 
 *     http://en.wikipedia.org/wiki/User-agent
 *
 * This is the name we use, which is admittedly arbitrary.
 */
const USER_AGENT = "XML-RPC-Example/1.0";

/**
 * This string contains our request in XML form.  The tag names should
 * be fairly obvious in meaning and intent.  The XML document
 * describes a <methodCall/> and that provides a useful way to think
 * about XML-RPC requests.  Imagine that we want the server to
 * execute this code
 *
 *     examples.getStateName(41)
 *
 * and return the value to us.  That is exactly what the XML in this
 * string represents, that method call and its parameters.
 */
const REQUEST_XML = "<?xml version=\"1.0\"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><int>41</int></value>
            </param>
        </params>
    </methodCall>";

/**
 * This is our HTTP request.  The XML-RPC specification says we have
 * to use the POST method.  Not only that, we must specify the
 * User-Agent, Content-Type, and the Content-Length.  A lot of the
 * code we are about to write will throw exceptions if there are any
 * errors, hence the try-catch block for any HttpException objects so
 * that we can see exactly what goes wrong.
 */
try
{
        $request = new HttpRequest(SERVER_URL, HttpRequest::METH_POST);
        $request->addHeaders([ "User-Agent"     => USER_AGENT,
                               "Content-Type"   => "text/xml",
                               "Content-Length" => strlen(REQUEST_XML) ]);
        $request->send();

        /**
         * The XML-RPC specification says that servers will always
         * return the status code '200 OK' unless there was an error.
         */
        if ($request->getResponseCode() !== 200)
        {
                die($request->getResponseBody());
        }
}
catch (HttpException $exception)
{
        die($exception->getMessage());
}

/**
 * If our program reaches this point then we made a successful request
 * and we can begin accessing the server's XML response like this.
 */
$response = new SimpleXMLElement($request->getResponseBody());

The XML-RPC response will also be an XML document, which will begin with a <methodResponse/> node which will have one of two child nodes:

  1. <params/> The return value(s) for a successful request.

  2. <fault/> A structure representing an error. I suggest looking at the XML-RPC specification for a good example of the design of the <fault/> tag.

Personally I prefer to use SimpleXML in PHP for parsing and extracting data from XML documents. PHP has some experimental, specific XML-RPC functions for such tasks as decoding requests. But considering their experimental nature I would not recommend using them.

And That’s About It

This covers all the basics for creating and sending XML-RPC requests. I tried to make the code and comments as explanatory as possible, but if something does not make sense (or you see an error) please let me know by leaving a comment. At this point I would recommend reading the specification to see other data you can put in requests, e.g. how you can represent array parameters.

I hope this article helps explain the basic concepts of XML-RPC requests. After this basic introduction of mine I would recommend reading a more comprehensive tutorial on the subject. And just to reiterate, I believe it is educational to handle these requests and responses ‘manually’, but for production software use existing tools instead of reinventing that wheel.

Advertisements

One thought on “Introduction to XML-RPC Requests With PHP

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s