JSON-RPC is a stateless, light-weight remote procedure call protocol encoded in JSON. It is a very simple protocol, defining only a handful of data types and commands.
Josser supports [JSON-RPC 1.0] (http://json-rpc.org/wiki/specification) and [revised JSON-RPC 2.0] (http://www.jsonrpc.org/specification). Unfortunately only client-server connections are possible with Josser - albeit JSON-RPC 1.0 was designed as P2P - due to PHP limitations.
It is worth to mention that Josser's architecture allows to plug your own JSON-RPC flavours or implement existing semi-standardized JSON-RPC protocols e.g. abandoned JSON-RPC 1.1WD.
As specification (both 1.0 and 2.0) states, JSON-RPC is transport agnostic. Josser sticks to that and allows to use http, sockets, tcp/ip or anything else your project requires (like post-it notes on a fridge :D). Currently only http transport is implemented.
Invoking remote methods is fairly simple:
<?php
namespace Josser;
use GuzzleHttp\Client;
use Josser\Client\Transport\Guzzle6Transport as HttpTransport; // there is also guzzle 5 implementation available
use Josser\Protocol\JsonRpc1;
$guzzle = new Client(['base_uri' => 'http://user:password@your-service.com/math:8888']); // http client
$transport = new HttpTransport($guzzle); // RPC over http
$protocol = new JsonRpc1; // lets use JSON-RPC 1.0
$client = new Client($transport, $protocol);
// send a request
$sum = $client->request('sum', array(5, 4));
var_dump($sum); // int(9)
If remote method does not return anything, notifications are what you need:
<?php
// instantiate client
$client->notify('logout');
Josser informs about errors through set of exceptions.
<?php
namespace Josser;
use Josser\Exception\RpcFaultException;
use Josser\Exception\TransportFailureException;
use Josser\Exception\RequestResponseMismatchException;
use Josser\Exception\InvalidResponseException;
use Josser\Exception\InvalidRequestException;
// instantiate client
try {
$client->request('method', array(1, "param2"));
} catch (RpcFaultException $e) {
echo 'Ups! Remote server sent an error.';
} catch (TransportFailureException $e) {
echo 'Josser did not send remote call.';
} catch (RequestResponseMismatchException $e) {
echo "Response id does not match request id.";
} catch (InvalidResponseException $e) {
echo "Response object is invalid due to protocol constraints.";
} catch(InvalidRequestException $e) {
echo "Request is invalid due to protocol constraints.";
}
For convenience catch-all exception exists.
<?php
namespace Josser;
use Josser\Client;
use Josser\Exception\JosserException;
// instantiate client
try {
$client->request('method', array(1, "param2"));
} catch (JosserException $e) {
echo 'Josser error occurred.';
}
When you call remote procedures, those calls are internally translated into generic request objects.
<?php
namespace Josser;
use Josser\Client;
use Josser\Client\Request\Request;
use Josser\Client\Request\Notification;
// instantiate transport and protocol
$client = new Client($transport, $protocol);
$client->request('math.divide', array(1, 2));
$client->notify('system.logout');
// code above is equivalent of
$request = new Request('math.divide', array(1, 2), 213123); // 213123 is a request identifier
$client->call($request);
$notification = new Notification('system.logout');
$client->call($notification);
As you can see, you can work with those low-level objects directly but downside of this approach is that you must provide your own id for every request. By default Client::request() generates this id for you on its own. Also remember that Client::call() does not return result directly - it return response object instead. To get to underlying result data use Response::getResult() like this:
<?php
namespace Josser;
use Josser\Client;
use Josser\Client\Request\Request;
use Josser\Client\Request\Notification;
// instantiate client
$request = new Request('math.sum', array(2, 2), 6564653);
$response = $client->call($request);
var_dump($response->getResult()); // int(4)
Notice the possibility of creating your own, project specific, request objects.
<?php
namespace MyProject\Request;
use Josser\Client\Request\Request;
class Divide extends Request
{
public function __construct($divident, $divisor)
{
$requestId = uniqid(); // random request id
parent::__construct('math.divide', array($divident, $divisor), $requestId);
}
}
PHP >= 5.3
Bugs and feature request are tracked on Github
Alan Gabriel Bem - alan.bem@gmail.com
Josser is licensed under the MIT License - see the LICENSE file for details