Installation
composer require lstrojny/fxmlrpc
Add to composer.json if not using autoloading:
"autoload": {
"psr-4": {
"App\\": "app/",
"Lstrojny\\XmlRpc\\": "vendor/lstrojny/fxmlrpc/src/"
}
}
Run composer dump-autoload.
First Request
use Lstrojny\XmlRpc\Client;
$client = new Client('http://example.com/xmlrpc');
$response = $client->call('methodName', ['arg1', 'arg2']);
Key Files to Review
src/Client.php (Core client logic)src/Request.php (Request building)src/Response.php (Response handling)tests/ (Usage examples and edge cases)$client = new Client('http://api.example.com/RPC2');
$result = $client->call('examples.getStateName', ['41']);
echo $result; // Outputs: "California"
// Passing complex data types
$client->call('system.method', [
'struct' => [
'member1' => 'value1',
'member2' => ['array', 'of', 'values'],
],
'array' => [1, 2, 3],
'int' => 42,
'double' => 3.14,
]);
$client = new Client('http://api.example.com/RPC2');
$client->setAuth('username', 'password'); // Basic Auth
// OR
$client->setHeaders(['X-API-Key' => 'your_key']);
$client->setBatchMode(true);
$client->call('method1', ['arg1']);
$client->call('method2', ['arg2']);
$responses = $client->getBatchResponses();
try {
$result = $client->call('methodName', ['args']);
} catch (\Lstrojny\XmlRpc\Exception\FaultException $e) {
// Handle XML-RPC fault (e.g., -32601: Invalid method)
echo "Fault: {$e->getFaultCode()} - {$e->getFaultString()}";
} catch (\Exception $e) {
// Handle transport/parsing errors
echo "Error: " . $e->getMessage();
}
// Service Provider (app/Providers/AppServiceProvider.php)
public function register()
{
$this->app->singleton('xmlrpc.client', function () {
return new \Lstrojny\XmlRpc\Client(config('services.xmlrpc.url'));
});
}
// Config (config/services.php)
'xmlrpc' => [
'url' => 'http://api.example.com/RPC2',
'timeout' => 10,
];
// Usage in Controller
$client = app('xmlrpc.client');
$data = $client->call('methodName', ['args']);
$client = new Client('http://api.example.com/RPC2');
$client->setMiddleware(function ($request, $next) {
\Log::debug('XML-RPC Request:', [
'url' => $request->getUri(),
'method' => $request->getMethod(),
'data' => $request->getData(),
]);
$response = $next($request);
\Log::debug('XML-RPC Response:', [
'status' => $response->getStatusCode(),
'data' => $response->getData(),
]);
return $response;
});
use Lstrojny\XmlRpc\Client;
use Lstrojny\XmlRpc\Exception\FaultException;
function callWithRetry(Client $client, string $method, array $args, int $retries = 3)
{
$lastException = null;
for ($i = 0; $i < $retries; $i++) {
try {
return $client->call($method, $args);
} catch (FaultException $e) {
$lastException = $e;
if ($i < $retries - 1) {
sleep(2 ** $i); // Exponential backoff
}
}
}
throw $lastException;
}
use Illuminate\Support\Facades\Cache;
function cachedCall(Client $client, string $method, array $args, string $cacheKey, int $ttl = 3600)
{
return Cache::remember($cacheKey, $ttl, function () use ($client, $method, $args) {
return $client->call($method, $args);
});
}
Fault Code Handling
-32601 for "Invalid method").FaultException separately from other exceptions.-32600: Invalid request-32601: Method not found-32602: Invalid arguments-32603: Internal errorData Type Mismatches
null vs. false) can cause issues.null as null (not false or '') to avoid ambiguity.Large Payloads
FaultException with -32000 (server error).UTF-8 Encoding
$client->setMiddleware(function ($request, $next) {
$request->setData(json_encode($request->getData(), JSON_UNESCAPED_UNICODE));
return $next($request);
});
SSL/TLS Issues
$client = new Client('https://insecure.example.com/RPC2');
$client->setOptions(['ssl' => ['verify_peer' => false]]);
Enable Verbose Logging
$client->setDebug(true); // Logs raw request/response
Inspect Raw Requests/Responses
$client->setMiddleware(function ($request, $next) {
\Log::debug('Raw Request:', $request->getRawData());
$response = $next($request);
\Log::debug('Raw Response:', $response->getRawData());
return $response;
});
Validate XML-RPC Structure
<methodCall>
<methodName>methodName</methodName>
<params>
<param><value><string>arg1</string></value></param>
<param><value><int>42</int></value></param>
</params>
</methodCall>
Custom Type Mappings
Lstrojny\XmlRpc\Type to handle custom PHP/XML-RPC type conversions.class CustomType extends \Lstrojny\XmlRpc\Type
{
public static function fromXml($xml, TypeFactory $factory)
{
// Custom logic to parse XML into PHP
}
public function toXml()
{
// Custom logic to serialize PHP to XML
}
}
$client = new Client('http://api.example.com/RPC2');
$client->getTypeFactory()->registerType('customType', CustomType::class);
Custom Transport Layer
Lstrojny\XmlRpc\Transport\TransportInterface for non-HTTP protocols (e.g., WebSockets).class WebSocketTransport implements TransportInterface
{
public
How can I help you explore Laravel packages today?