XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.

advertisement

Building Web Services with FileMaker Pro
by Bill Humphries | Pages: 1, 2, 3, 4

Using PRAX to Display Query Results

PRAX is a PHP implementation of RAX, a record-oriented API for processing XML. For the row-record style results from the dso_xml syntax, it provides a simple way to format the results.

PRAX has a straightforward API: to import XML, create a RAX object and read a file or URL.

include("prax.inc");
$rax = new RAX();
$rax->openfile($url);

Then specify an element to use as record delimiter, and parse the document.

$rax->record_delim = "ROW";
$rax->parse();

Then to write out the records as an HTML table:

if( $rec = $rax->readRecord())
  {
  $row = 1;
  $names   = $rec->getFieldNames();
  print "<table cellpadding=\"5\" 
    cellspacing=\"0\">\n\t<tr>\n";
  while ($name = array_shift($names))
  {
    print "<th class=\"header\">".$name."</th>\n";
  }
  print "\t</tr>\n\t";
  print "<tr>\n";
  while ( $rec ) 
  {
  
    $class = oddOrEven($row);
    
    print "<tr>";
    $values = $rec->getFields();
    while ($value = array_shift($values))
    {
      print "<td class=\"".$class."\">". 
        $value."</td>\n";
    }
    print "</tr>";
    $rec = $rax->readRecord();
    $row++;
  }
  print "</table>";
  }
  else
  {
    print "<p>There were no results returned.
Either an error occurred on the FMPro Server, or no records 
matched your query.</p>";
}

This results in HTML rendered like the following table:

Name Phone Location
Jody Tester 512 111-2222 Austin
Mary Sysadmin 512 222-3333 Austin
Joe Developer 408 444-5555 Cupertino
Bob Analyst 916 666-7777 Sacramento
Karen Project 508 666-7777 Cupertino

Making requests with GET

If you request the script through HTTP GET, you will want to look at the request's query string (split over several lines here for readability),

<a href="list.php?http://localhost:471/FMPro?
-db=phonelist.fp5&-format=-dso_xml&-find">
Show phone list</a>

and assign it to the FileMaker Pro URL you want to request within your script.

The complete PHP source is in list.php.

Error Handling

The script in list.php tests to see if PRAX can return a record. But it does not distinguish between a case where there are no records matching a query and the case of an error occurring on the server due to, say, a malformed query URL.

Using the dso_xml syntax, FileMaker Pro returns "401" in the ERRORCODE element, for example, when there are no records matching a query.

Using XML-RPC to Display Query Results

XML-RPC provides another way to connect to the FileMaker Pro database. Since XML-RPC clients exist for many platforms (see xmlrpc.org for a list of implementations) you can connect FileMaker Pro databases to web server clients running on Linux and Unix.

XML-RPC servers can provide several services (in PHP, one script would define each service), so it can provide a convenient container for editing, displaying, and creating records in the FileMaker Pro database.

Moving to an RPC framework also provides infrastructure for handling and reporting errors.

So next we'll build an XML-RPC client and server using the classes from the XML-RPC project on SourceForge.

XML-RPC Server

The following code fragment is part of an XML-RPC server with the supporting the method FMPro.allRecords. It takes the name of a database and returns a Base64 encoded string with the response XML.

function allrecords($m)
{
  global $xmlrpcerruser;
  $err = "";
  
  // decode parameters
  $dbName = xmlrpc_decode($m->getParam(0));
  
  $url = "http://localhost:471/FMPro?-db=".
    $dbName."&-format=-dso_xml&-find";
  
  // now try to read from it
  // prepend @ to function to suppress errors to stdout
  $buffer = "";
  $fp = @fopen($url,"r");
  
  xmlrpc_debugmsg("Got $fp from trying to open $url.");
  
  // read response
  if ($fp)
  {
    while(!feof($fp))
    {
      $next = fread($fp,4096);
      xmlrpc_debugmsg("Got $next from fread on $fp.");      
      $buffer = $buffer.$next;
    }
    fclose($fp);
  }
  else
  {
    $err = "Unable to connect or read from $url.";
  }
  
  // Return response or error.
  if ($err)
  {
    return new xmlrpcresp(0, $xmlrpcerruser, $err);
  }
  else
  {
    xmlrpc_debugmsg("Got from FMPro Server: $buffer");
    $base64String = base64_encode($buffer);
    return new xmlrpcresp(new xmlrpcval( 
      $base64String,$xmlrpcString));
  }
}

XML-RPC Client

The counterpart client script defines a function to call the allRecords method on the server.

function getAllRecords($dbName)
{
  $client = new xmlrpc_client("/FMPro/FMProServer.php",
    "localhost",80);
  $client->setDebug(1);
  
  $msg = new xmlrpcmsg("FMPro.allRecords");
  $msg->addParam(new xmlrpcval($dbName, $xmlrpcString));
  // Dump the wire message sent
  print "<p>Sending message:</p>";
  print "<pre>". htmlentities($msg->serialize())
    . "</pre>";
  
  $result = $client->send($msg,30);
  
  if ($result)
  {
    print "<p>Got a response.</p>";
    if ($result->value())
    {
      print "<p>Got a valid response.</p>";
      // The result is a Base64 encoded string
      $encodedResult = xmlrpc_decode($result->value(),
                         $xmlrpcString);
      $decodedResult = base64_decode($encodedResult);
      // Dump the response sent
      print "<p>Got response:</p>";
      print "<pre>" . htmlentities($decodedResult).
        "</pre>";
      return $decodedResult;
    }
    else
    {
      print "<p>A fault occured.</p>";
      print "<p>".
          $base64Result->faultCode().
          ", explanation: ".
          $base64Result->faultString().
          "</p>";
    }
  }
  else
  {
    print "<p>A Low Level Error Occured.</p>";
    print "<p>Error # " . $client->errno . ": ".
        $client->errstr . "</p>";
    exit(0);
  }
}  

To get around problems with passing XML strings in XML-RPC, the server encodes the response in Base64 before sending it. The client decodes the incoming string and returns it.

The scripts for the XML-RPC server are

xmlrpcList.php demonstrates the service. Debugging is turned on so you can see the stages of the request.

Pages: 1, 2, 3, 4

Next Pagearrow