Sample PHP Services Client Code

Events happening in the community are now at Drupal community events on www.drupal.org.
You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

Updated code 9/30/2009. Uses Services 6.x-2.x-dev on Drupal 6.14; XML-RPC for PHP library at http://phpxmlrpc.sourceforge.net/. Thanks to clues from http://drupal.org/node/303285 and the services tester, it includes some code for populating CCK fields ("field_publication", "field_byline", etc.). This is pre-production code for importing articles to a newspaper website, designed to run on the command line. I just left the parseXML() function as an example.

<?php
 
require('./xmlrpc-3.0.0.beta/lib/xmlrpc.inc');
 
$username = "username";
 
$pass = "password";
 
$domain = "example.com";
 
$publication = "The Daily Drupal";
 
$servicehost = "example.com";
 
$servicepath = "services/xmlrpc";
 
$sessid = "";
 
$uid = 0;
 
$xmlpath = "/path/to/xml";
 
$processdir = "/path/to/processed";
 
$successdir = "$processdir/success";
 
$failuredir = "$processdir/failure";
 
 
// Make initial connection to get a session ID
 
$m = new xmlrpcmsg('system.connect', array());
 
$c = new xmlrpc_client($servicepath, $servicehost, 80);
 
$c->return_type = "phpvals";
 
 
$r = &$c->send($m);
  if(!
$r->faultCode()){
   
$v = $r->value();
   
$sessid = ($v['sessid']);
  }else{
    die(
"An error occurred on system.connect: ".$r->faultString()."\n");
  }

 
// Using the session ID from the first connection, log in to the server
 
$m = new xmlrpcmsg("user.login",
    array(
      new
xmlrpcval($sessid),
      new
xmlrpcval($username),
      new
xmlrpcval($pass))
  );
 
// If login is successful, user object and a new sessid will be returned
 
$r = &$c->send($m);
  if(!
$r->faultCode()){
   
$v = $r->value();
   
// Only need uid for our purposes
   
$uid = $v['user']['uid'];
   
$user = $v['user'];
   
$sessid = $v['sessid'];
  }else{
    die(
"An error occurred on user.login: ".$r->faultString()."\n");
  }
 
 
// Open the XML directory and iterate files
 
$dir_handle = @opendir($xmlpath) or die("Unable to open $xmlpath\n");
 
  while (
$file = readdir($dir_handle))
  {
   
// Only get files named *.xml
   
if(end(explode(".", $file)) != "xml")
      continue;
   
   
// Ignore parsing errors for now and continue
   
libxml_use_internal_errors(true);
   
$xmldoc = simplexml_load_file("$xmlpath/$file");
    if(!
$xmldoc){
     
rename("$xmlpath/$file", "$failuredir/$file");
      continue;
    }
   
   
// Pass the XML to be parsed and get back a PHP node structure
   
$node = parseXml(&$xmldoc);
   
// Call the service to create the node
   
$nid = createNode($sessid, &$node);
   
   
// Move file to success or failure directory
   
if($nid > 0){
     
rename("$xmlpath/$file", "$successdir/$file");
      print
"Node $nid created.\n";
    }
    else{
     
rename("$xmlpath/$file", "$failuredir/$file");
    }
  }
 
 
closedir($dir_handle);
 
  function
parseXML($xmldoc){
    global
$publication;
   
// Initialize array container for node data
   
$node = array();
   
   
$node["publication"] = $publication;
   
$node["type"] = "story";
   
$node["format"] = 2;
   
   
$tmp = $xmldoc->xpath("//meta[@name='feed.doc.name']");
   
$node["filename"] = trim($tmp[0]['content']);
   
   
$tmp = $xmldoc->xpath("//meta[@name='feed.doc.id']");
   
$node["docid"] = trim($tmp[0]['content']);
   
   
$tmp = $xmldoc->xpath("//meta[@name='cms.release']");
   
// This must be formatted as in the node edit form rather than a timestamp
   
$node["releasedate"] = date('Y-m-d H:i:s O', strtotime(trim($tmp[0]['content'])));
   
   
$tmp = $xmldoc->xpath("//meta[@name='cms.expire']");
   
$node["expiredate"] = strtotime(trim($tmp[0]['content']));
   
   
$tmp = $xmldoc->xpath("//meta[@name='cms.section']");
   
$node["section"] = trim($tmp[0]['content']);

   
$tmp = $xmldoc->xpath("//meta[@name='cms.category']");
   
$node["category"] = trim($tmp[0]['content']);

   
$tmp = $xmldoc->xpath("//meta[@name='position.rank']");
   
$node["positionrank"] = trim($tmp[0]['value']);
   
   
$tmp = $xmldoc->xpath("//pubdata");
   
$node["positionsection"] = trim($tmp[0]['position.section']);
   
$node["positionsequence"] = trim($tmp[0]['position.sequence']);
   
$node["sectionname"] = trim($tmp[0]['name']);
   
   
$node["headline"] = $xmldoc->body->{'body.head'}->hedline->hl1;
   
   
$node["subhead"] = $xmldoc->body->{'body.head'}->hedline->hl2;
   
   
$node["byline"] = $xmldoc->body->{'body.head'}->byline->person;
   
   
$node["bylinecredit"] = $xmldoc->body->{'body.head'}->bylinecredit->site;
   
   
// Try to access the body in different ways to account for screwy XML
   
$tmp = $xmldoc->body->{'body.content'};
    foreach(
$tmp->children() as $element){
      if(
$element->getName() !== "media")
       
$node["body"] .= $element->asXML();
    }
   
    if(
$node["body"] === "")
     
$node["body"] = $xmldoc->body->{'body.content'};
   
   
// Ampersands are encoded but need to be unencoded for other HTML characters
   
$node["body"] = preg_replace("/&amp;/", "&", $node["body"]);
   
    return
$node;
  }
 
 
// Handle node.save and CCK fields
 
function createNode($sessid, $node){
    global
$c, $uid, $username;
   
$nid = 0;
   
   
$edit = new xmlrpcval(
      array(
       
"uid" => new xmlrpcval($uid, "int"),
       
"name" => new xmlrpcval($username),
       
"type" => new xmlrpcval($node["type"]),
       
"format" => new xmlrpcval($node["format"], "int"),
       
"date" => new xmlrpcval($node["releasedate"]),
       
"title" => new xmlrpcval($node["headline"]),
       
"body" => new xmlrpcval($node["body"]),
       
"field_publication" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["publication"])), "struct")), "array"),
       
"field_byline" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["byline"])), "struct")), "array"),
       
"field_section" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["section"])), "struct")), "array"),
       
"field_category" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["category"])), "struct")), "array"),
       
"field_sectionname" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["sectionname"])), "struct")), "array"),
       
"field_positionsection" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["positionsection"])), "struct")), "array"),
       
"field_positionsequence" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["positionsequence"])), "struct")), "array"),
       
"field_positionrank" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["positionrank"], "int")), "struct")), "array"),
       
"field_expiredate" => new xmlrpcval(array(new xmlrpcval(array("value" => new xmlrpcval($node["expiredate"])), "struct")), "array")
      ),
     
"struct"
   
);
   
   
$m = new xmlrpcmsg("node.save",
      array(
        new
xmlrpcval($sessid),
       
$edit
     
)
    );
   
   
$r = &$c->send($m);
    if(!
$r->faultCode()){
     
$nid = $r->value();
    }else{
      print (
"An error occurred on node.save: ".$r->faultString()."\n");
     
$nid = 0;
    }
   
    return
$nid;
  }
?>

Services

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: