Error Management
If you try to replace the method you are calling with any method you did not implement, the service will automatically trigger an error, which will be caught by the client and can be checked via the faultCode() method. So if we change one line in the client script to:
$message = new XML_RPC_Message('label.getArtists', $params);
The output of the script is:
Could not use the XML-RPC service. Unknown method
As we did not implement the method, the service will signal the error automatically without any intervention needed by the developer. But of course the user still could make some mistake while using the client, for example if there is a typo in the name of the artist that he or she passes in:
new XML_RPC_Value('Elvis Prely', 'string')
$message = new XML_RPC_Message('label.getRecords', $params);
If you run this script, the output is: 0
This happens because the original getRecords() method returns false when receiving an unknown artist and, as PHP is not type-safe, this results in the return value 0 on the client. Of course it would be better to signal an error in the XML-RPC server, which can be caught by the client as well. Signaling an error can be done by using a different signature for the XML_RPC_Response constructor. Instead of passing in an XML_RPC_Value, we pass 0 as the first parameter, followed by a fault code and a textual error message:
function getRecordsService($args) {
$artist = $args->getParam(0)->scalarval(); $records = getRecords($artist);
$response = new XML_RPC_Response(0, 50,
'The artist "'.$artist.'" is not in our database.');
$val = XML_RPC_encode($records); $response = new XML_RPC_Response($val);
return $response;
If we run the client script again after we have made this change, it will now output:
Could not use the XML-RPC service. The artist "Elvis Prely" is not in our database.
This will tell the client a lot more about the problem that occurred than just returning 0. Now there is only one problem left. Imagine a client calling the method without any parameters at all:
$message = new XML_RPC_Message('label.getRecords'); This will result in the following output:
Could not use the XML-RPC service. Invalid return payload: enable debugging to examine incoming payload
If we enable debugging in the client using $client->setDebug(1); we will see the source of the problem:
<b>Fatal error</b>: Call to undefined method XML_RPC_Response:: scalarval() in <b>/var/www/record-label.php</b> on line <b>21</b><br />
We tried to call the scalarval() method on an XML_RPC_value that is not present in the actual request. We could easily solve this by checking whether a parameter has been passed in and signaling a fault otherwise, but there is an easier way to automate this. When creating the dispatch map for the XML-RPC service, besides defining a PHP function for each method of the service, it is also possible to specify the method signature for this method:
'function' => 'getRecordsService', 'signature' => array(
arrayfarray1, "string"),
The signature is an array as it is possible to overload the method and use it with different signatures. For each permutation you have to specify the return type (in this case an array) and the parameters the method accepts. As our method only accepts a string, we only define one method signature. Now if you run the client again, there will be a new error message, which is a lot more useful:
Could not use the XML-RPC service. Incorrect parameters passed to method: Signature permits 1 parameters but the request had 0
You probably already noticed the additional entry docstring that we added to the dispatch map in the last example. This has been added to showcase another feature of the XML_RPC_server class—it automatically adds to each XML-RPC service several methods that provide introspection features. This allows you to get a list of all supported methods of the service via any XML-RPC client:
require_once 'XML/RPC.php';
$client = new XML_RPC_Client('/record-label.php', 'localhost');
$message = new XML_RPC_Message('system.listMethods');
$value = $response->value(); $methods = XML_RPC_decode($value);
print_r($methods); If you run this script, it will display a list of all methods offered by the service:
Array (
[1] => system.listMethods
[2] => system.methodHelp
[3] => system.methodSignature
In the same way you can also get more information about one of the supported methods, which is why we added the docstring property to our dispatch map:
$message = new XML_RPC_Message('system.methodHelp', array(new XML_RPC_Value( 'label.getRecords'))); $response = $client->send($message);
$value = $response->value(); $help = XML_RPC_decode($value);
echo $help;
Running this script will display the help text we added for the label.getRecords() method. Whenever you implement an XML-RPC based service, you should always add this information to the dispatch map to make it easier for service consumers to use your service.
Now you know everything that you need to offer your own XML-RPC-based web service with the XML_RPC package and you can start offering your services to a variety of users, applications, and programming languages.
Post a comment