Community Documentation

Services 6.x-2.0 PHP example using XML-RPC for PHP

Last updated June 10, 2010. Created by jp.stacey on June 3, 2010.
Log in to edit this page.

This example is to show you a basic method call (so not including e.g. API keys) and how to construct the URL. On your XMLRPC server website you will need these Drupal modules enabled:

  • services
  • XMLRPC server for services
  • node services

You also need all relevant permissions set to allow access; and, for this example to work out of the box, uncheck the requirements of API keys and session IDs. For security reasons you will need to set all of this up eventually.

XML-RPC for PHP is a freely available standalone library for consuming XMLRPC feeds in PHP. It gets around common problems of e.g. other libraries being deprecated, or not available on your server. You can put it in e.g. sites/all/libraries rather than cluttering up your codebase with it.

Here's a basic example for how to use it to retrieve a node from a Drupal site. This client-side code is independent of Drupal: it's just PHP which would consume XMLRPC service provided by the Services modules on the existing Drupal site.

<?php
function rpcexample_retrieve_node($nid) {
 
// Load the XML-RPC for PHP library from wherever you've put it
  // File path relative to the Drupal root
 
require_once("sites/all/libraries/xmlrpc/lib/xmlrpc.inc");

 
// Turn the node ID into a standard XMLRPC data type, for transmission
 
$nid = new xmlrpcval($nid, "int");

 
// Create an XMLRPC message
 
$m = new xmlrpcmsg('node.load',
   
// Note that the "optional" second parameter is required, but it can be empty.
    // If you omit it, services returns wrong-parameter-number errors
   
array($nid, new xmlrpcval(array(), "array"))
  );

 
// Create a connection to the remote server
  // Note the root URL is services/xmlrpc. If you don't turn the
  // separate XMLRPC server module on, this will result in HTTP 404
 
$c = new xmlrpc_client('/services/xmlrpc', 'remote-server.example.com', 80);

 
// Send the message to the remote server and get the response
 
$r = $c->send($m);

 
// The return value is a collection of xmlrpcval objects
  // which you can loop over to turn back into PHP data types
 
return $r->value();
}
?>

The return value from XMLRPC for PHP is typically a parent-child tree of the slightly opaque xmlrpcval objects. That's a bit annoying, but here's a standard function which recursively converts these into nested arrays and structs instead:

<?php
/**
* Turn xmlrpcval back into PHP-native, recursively
*/
function rpcexample_rpc_convert($x) {
 
$keys = array_keys($x->me);
 
$val = &$x->me[$keys[0]];

  switch(
$x->mytype) {
   
// Scalar
   
case 1:
      return
$val;
   
// Array
   
case 2:
     
$ret = array();
      foreach(
$val as $v) {
       
// Don't preserve keys
       
$ret[] = rpcexample_rpc_convert($v);
      }
      return
$ret;
   
// Struct
   
case 3:
     
$ret = array();
      foreach(
$val as $k => $v) {
       
// Preserve keys
       
$ret[$k] = rpcexample_rpc_convert($v);
      }
      return
$ret;
  }
}
?>

Comments

Examples don't work for me

I've download the PHPXMLRPC library, enabled Echo Service, XMLRPC Server, Node Service and Key Authentication. I've unchecked key and session id in the services "Settings". I modified the example to use node.get. I just get back "Access Denied".

node.get needs permission set

If you look on the module permissions page there is a permission to be set for node_service, even if you have no authentification set in the services settings you'll get access denied if anonymous users don't have the access node_service permission.

Same thing using API key authentication

<?php
function rpcexample_retrieve_node_with_api_key($nid,$use_sessid=TRUE) {
  // API key as generated in the Services "Keys" page
  $key = '0000000000000000000000000000';

  //domain which you authorized to use this key in the Services "Keys" page
  $domain = 'client.example.com';

  // create client
  $client = new xmlrpc_client('/services/xmlrpc', 'remote-server.example.com', 80);

  // get a session id
  // this is necessary unless you have unchecked the "use sessid" box on the Services "Settings" page
  if ($use_sessid) {
    $message = new xmlrpcmsg('system.connect',array());
    $resp = $client->send($message);
    $data = rpcexample_rpc_convert($resp->value());
    $sessid = $data['sessid'];
  }

  // prepare authentication token
  $timestamp = (string) strtotime("now");
  $nonce = user_password(10); // this uses a drupal function, but any random string will do
  $method_name = 'node.get';
  $hash = hash_hmac("sha256", "$timestamp;$domain;$nonce;$method_name", $key);

  // parameters
  $params = array(
    new xmlrpcval($hash,'string'),
    new xmlrpcval($domain,'string'),
    new xmlrpcval($timestamp,'string'),
    new xmlrpcval($nonce,'string'),
  );
  if ($use_sessid) {
    $params[] = new xmlrpcval($sessid,'string');
  }
  $params[] = new xmlrpcval($nid,'int');
  //second argument is now really optional
 
  $message = new xmlrpcmsg($method_name,$params);
  $resp = $client->send($message);
  $data = rpcexample_rpc_convert($resp->value());
  if ($data) {
    print_r($data);
  }
  else {
    print("Error $resp->errno: $resp->errstr\n");
  }
}

Page status

No known problems

Log in to edit this page

About this page

Drupal version
Drupal 6.x
Audience
Programmers

Develop for Drupal

Drupal’s online documentation is © 2000-2013 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.
nobody click here