1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.json.server">
4 <title>Zend_Json_Server - JSON-RPC server</title>
7 <classname>Zend_Json_Server</classname> is a <ulink
8 url="http://groups.google.com/group/json-rpc/">JSON-RPC</ulink> server implementation.
9 It supports both the <ulink url="http://json-rpc.org/wiki/specification">JSON-RPC
10 version 1 specification</ulink> as well as the <ulink
11 url="http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal">version 2
12 specification</ulink>; additionally, it provides a <acronym>PHP</acronym> implementation
14 url="http://groups.google.com/group/json-schema/web/service-mapping-description-proposal">Service
15 Mapping Description (SMD) specification</ulink>
16 for providing service metadata to service consumers.
20 JSON-RPC is a lightweight Remote Procedure Call protocol that utilizes
21 <acronym>JSON</acronym> for its messaging envelopes. This JSON-RPC implementation follows
22 <acronym>PHP</acronym>'s <ulink
23 url="http://www.php.net/manual/en/class.soapserver.php">SoapServer</ulink>
24 <acronym>API</acronym>. This means, in a typical situation, you will simply:
28 <listitem><para>Instantiate the server object</para></listitem>
31 <para>Attach one or more functions and/or classes/objects to the server object</para>
34 <listitem><para>handle() the request</para></listitem>
38 <classname>Zend_Json_Server</classname> utilizes <xref linkend="zend.server.reflection" />
39 to perform reflection on any attached classes or functions, and uses that
40 information to build both the SMD and enforce method call signatures. As
41 such, it is imperative that any attached functions and/or class methods
42 have full <acronym>PHP</acronym> docblocks documenting, minimally:
46 <listitem><para>All parameters and their expected variable types</para></listitem>
47 <listitem><para>The return value variable type</para></listitem>
51 <classname>Zend_Json_Server</classname> listens for POST requests only at this
52 time; fortunately, most JSON-RPC client implementations in the wild at
53 the time of this writing will only POST requests as it is. This makes it
54 simple to utilize the same server end point to both handle requests as
55 well as to deliver the service SMD, as is shown in the next example.
58 <example id="zend.json.server.usage">
59 <title>Zend_Json_Server Usage</title>
62 First, let's define a class we wish to expose via the JSON-RPC
63 server. We'll call the class 'Calculator', and define methods for
64 'add', 'subtract', 'multiply', and 'divide':
67 <programlisting language="php"><![CDATA[
69 * Calculator - sample class to expose via JSON-RPC
74 * Return sum of two variables
80 public function add($x, $y)
86 * Return difference of two variables
92 public function subtract($x, $y)
98 * Return product of two variables
104 public function multiply($x, $y)
110 * Return the division of two variables
116 public function divide($x, $y)
124 Note that each method has a docblock with entries indicating each
125 parameter and its type, as well as an entry for the return value.
126 This is <emphasis>absolutely critical</emphasis> when utilizing
127 <classname>Zend_Json_Server</classname> or any other server component in
128 Zend Framework, for that matter.
132 Now we'll create a script to handle the requests:
135 <programlisting language="php"><![CDATA[
136 $server = new Zend_Json_Server();
138 // Indicate what functionality is available:
139 $server->setClass('Calculator');
141 // Handle the request:
146 However, this will not address the issue of returning an SMD so that
147 the JSON-RPC client can autodiscover methods. That can be
148 accomplished by determining the <acronym>HTTP</acronym> request method, and then
149 specifying some server metadata:
152 <programlisting language="php"><![CDATA[
153 $server = new Zend_Json_Server();
154 $server->setClass('Calculator');
156 if ('GET' == $_SERVER['REQUEST_METHOD']) {
157 // Indicate the URL endpoint, and the JSON-RPC version used:
158 $server->setTarget('/json-rpc.php')
159 ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
162 $smd = $server->getServiceMap();
164 // Return the SMD to the client
165 header('Content-Type: application/json');
174 If utilizing the JSON-RPC server with Dojo toolkit, you will also
175 need to set a special compatibility flag to ensure that the two
176 interoperate properly:
179 <programlisting language="php"><![CDATA[
180 $server = new Zend_Json_Server();
181 $server->setClass('Calculator');
183 if ('GET' == $_SERVER['REQUEST_METHOD']) {
184 $server->setTarget('/json-rpc.php')
185 ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
186 $smd = $server->getServiceMap();
188 // Set Dojo compatibility:
189 $smd->setDojoCompatible(true);
191 header('Content-Type: application/json');
200 <sect2 id="zend.json.server.details">
201 <title>Advanced Details</title>
204 While most functionality for <classname>Zend_Json_Server</classname> is
205 spelled out in <xref linkend="zend.json.server.usage" />, more
206 advanced functionality is available.
209 <sect3 id="zend.json.server.details.zendjsonserver">
210 <title>Zend_Json_Server</title>
213 <classname>Zend_Json_Server</classname> is the core class in the JSON-RPC
214 offering; it handles all requests and returns the response
215 payload. It has the following methods:
221 <methodname>addFunction($function)</methodname>: Specify a
222 userland function to attach to the server.
228 <methodname>setClass($class)</methodname>: Specify a class
229 or object to attach to the server; all public methods of
230 that item will be exposed as JSON-RPC methods.
236 <code>fault($fault = null, $code = 404, $data = null)</code>: Create and
237 return a <classname>Zend_Json_Server_Error</classname> object.
243 <methodname>handle($request = false)</methodname>: Handle a
244 JSON-RPC request; optionally, pass a
245 <classname>Zend_Json_Server_Request</classname> object to utilize
246 (creates one by default).
252 <methodname>getFunctions()</methodname>: Return a list of
253 all attached methods.
259 <code>setRequest(Zend_Json_Server_Request $request)</code>: Specify a
260 request object for the server to utilize.
266 <methodname>getRequest()</methodname>: Retrieve the request
267 object used by the server.
273 <code>setResponse(Zend_Json_Server_Response $response)</code>: Set the
274 response object for the server to utilize.
280 <methodname>getResponse()</methodname>: Retrieve the
281 response object used by the server.
287 <methodname>setAutoEmitResponse($flag)</methodname>:
288 Indicate whether the server should automatically emit
289 the response and all headers; by default, this is
290 <constant>TRUE</constant>.
296 <methodname>autoEmitResponse()</methodname>: Determine if
297 auto-emission of the response is enabled.
303 <methodname>getServiceMap()</methodname>: Retrieve the
304 service map description in the form of a
305 <classname>Zend_Json_Server_Smd</classname> object
311 <sect3 id="zend.json.server.details.zendjsonserverrequest">
312 <title>Zend_Json_Server_Request</title>
315 The JSON-RPC request environment is encapsulated in the
316 <classname>Zend_Json_Server_Request</classname> object. This object allows
317 you to set necessary portions of the JSON-RPC request, including
318 the request ID, parameters, and JSON-RPC specification version.
319 It has the ability to load itself via <acronym>JSON</acronym> or a set of options,
320 and can render itself as <acronym>JSON</acronym> via the
321 <methodname>toJson()</methodname> method.
325 The request object has the following methods available:
331 <methodname>setOptions(array $options)</methodname>: Specify
332 object configuration. <varname>$options</varname> may contain
333 keys matching any 'set' method:
334 <methodname>setParams()</methodname>, <methodname>setMethod()</methodname>,
335 <methodname>setId()</methodname>, and
336 <methodname>setVersion()</methodname>.
342 <methodname>addParam($value, $key = null)</methodname>: Add
343 a parameter to use with the method call. Parameters can be
344 just the values, or can optionally include the parameter name.
350 <methodname>addParams(array $params)</methodname>: Add
351 multiple parameters at once; proxies to
352 <methodname>addParam()</methodname>
358 <methodname>setParams(array $params)</methodname>: Set all
359 parameters at once; overwrites any existing parameters.
365 <methodname>getParam($index)</methodname>: Retrieve a
366 parameter by position or name.
372 <methodname>getParams()</methodname>: Retrieve all parameters at once.
378 <methodname>setMethod($name)</methodname>: Set the method to call.
384 <methodname>getMethod()</methodname>: Retrieve the method
391 <methodname>isMethodError()</methodname>: Determine whether
392 or not the request is malformed and would result in an error.
398 <methodname>setId($name)</methodname>: Set the request
399 identifier (used by the client to match requests to responses).
405 <methodname>getId()</methodname>: Retrieve the request identifier.
411 <methodname>setVersion($version)</methodname>: Set the
412 JSON-RPC specification version the request conforms to.
413 May be either '1.0' or '2.0'.
419 <methodname>getVersion()</methodname>: Retrieve the JSON-RPC
420 specification version used by the request.
426 <methodname>loadJson($json)</methodname>: Load the request
427 object from a <acronym>JSON</acronym> string.
433 <methodname>toJson()</methodname>: Render the request as
434 a <acronym>JSON</acronym> string.
440 An <acronym>HTTP</acronym> specific version is available via
441 <classname>Zend_Json_Server_Request_Http</classname>. This class will
442 retrieve the request via <code>php://input</code>, and allows access to the raw
443 <acronym>JSON</acronym> via the <methodname>getRawJson()</methodname> method.
447 <sect3 id="zend.json.server.details.zendjsonserverresponse">
448 <title>Zend_Json_Server_Response</title>
451 The JSON-RPC response payload is encapsulated in the
452 <classname>Zend_Json_Server_Response</classname> object. This object allows
453 you to set the return value of the request, whether or not the
454 response is an error, the request identifier, the JSON-RPC
455 specification version the response conforms to, and optionally
460 The response object has the following methods available:
466 <methodname>setResult($value)</methodname>: Set the response result.
472 <methodname>getResult()</methodname>: Retrieve the response result.
478 <code>setError(Zend_Json_Server_Error $error)</code>: Set an error object.
479 If set, this will be used as the response when serializing to
480 <acronym>JSON</acronym>.
486 <methodname>getError()</methodname>: Retrieve the error object, if any.
492 <methodname>isError()</methodname>: Whether or not the response is an error
499 <methodname>setId($name)</methodname>: Set the request identifier (so the
500 client may match the response with the original request).
506 <methodname>getId()</methodname>: Retrieve the request identifier.
512 <methodname>setVersion($version)</methodname>: Set the
513 JSON-RPC version the response conforms to.
519 <methodname>getVersion()</methodname>: Retrieve the JSON-RPC
520 version the response conforms to.
526 <methodname>toJson()</methodname>: Serialize the response to
527 <acronym>JSON</acronym>. If the response is an error response, serializes
534 <methodname>setServiceMap($serviceMap)</methodname>: Set the
535 service map object for the response.
541 <methodname>getServiceMap()</methodname>: Retrieve the
542 service map object, if any.
548 An <acronym>HTTP</acronym> specific version is available via
549 <classname>Zend_Json_Server_Response_Http</classname>. This class will
550 send the appropriate <acronym>HTTP</acronym> headers as well as serialize the
551 response as <acronym>JSON</acronym>.
555 <sect3 id="zend.json.server.details.zendjsonservererror">
556 <title>Zend_Json_Server_Error</title>
559 JSON-RPC has a special format for reporting error conditions.
560 All errors need to provide, minimally, an error message and error
561 code; optionally, they can provide additional data, such as a
566 Error codes are derived from those recommended by <ulink
567 url="http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php">the
568 XML-RPC EPI project</ulink>. <classname>Zend_Json_Server</classname>
569 appropriately assigns the code based on the error condition. For
570 application exceptions, the code '-32000' is used.
574 <classname>Zend_Json_Server_Error</classname> exposes the following
581 <methodname>setCode($code)</methodname>: Set the error code;
582 if the code is not in the accepted XML-RPC error code range,
583 -32000 will be assigned.
589 <methodname>getCode()</methodname>: Retrieve the current error code.
595 <methodname>setMessage($message)</methodname>: Set the error message.
601 <methodname>getMessage()</methodname>: Retrieve the current error message.
607 <methodname>setData($data)</methodname>: Set auxiliary data
608 further qualifying the error, such as a backtrace.
614 <methodname>getData()</methodname>: Retrieve any current auxiliary error
621 <methodname>toArray()</methodname>: Cast the error to an
622 array. The array will contain the keys 'code', 'message', and 'data'.
628 <methodname>toJson()</methodname>: Cast the error to a
629 JSON-RPC error representation.
635 <sect3 id="zend.json.server.details.zendjsonserversmd">
636 <title>Zend_Json_Server_Smd</title>
639 SMD stands for Service Mapping Description, a <acronym>JSON</acronym> schema that
640 defines how a client can interact with a particular web service.
641 At the time of this writing, the <ulink
642 url="http://groups.google.com/group/json-schema/web/service-mapping-description-proposal">specification</ulink>
643 has not yet been formally ratified, but it is in use already
644 within Dojo toolkit as well as other JSON-RPC consumer clients.
648 At its most basic, a Service Mapping Description indicates the
649 method of transport (POST, GET, <acronym>TCP</acronym>/IP, etc), the request
650 envelope type (usually based on the protocol of the server), the
651 target <acronym>URL</acronym> of the service provider, and a map of services
652 available. In the case of JSON-RPC, the service map is a list of
653 available methods, which each method documenting the available
654 parameters and their types, as well as the expected return value
659 <classname>Zend_Json_Server_Smd</classname> provides an object oriented
660 way to build service maps. At its most basic, you pass it
661 metadata describing the service using mutators, and specify
662 services (methods and functions).
666 The service descriptions themselves are typically instances of
667 <classname>Zend_Json_Server_Smd_Service</classname>; you can also pass all
668 information as an array to the various service mutators in
669 <classname>Zend_Json_Server_Smd</classname>, and it will instantiate a
670 service object for you. The service objects contain information
671 such as the name of the service (typically the function or
672 method name), the parameters (names, types, and position), and
673 the return value type. Optionally, each service can have its own
674 target and envelope, though this functionality is rarely used.
678 <classname>Zend_Json_Server</classname> actually does all of this behind
679 the scenes for you, by using reflection on the attached classes
680 and functions; you should create your own service maps only if
681 you need to provide custom functionality that class and function
682 introspection cannot offer.
686 Methods available in <classname>Zend_Json_Server_Smd</classname> include:
692 <methodname>setOptions(array $options)</methodname>: Setup
693 an SMD object from an array of options. All mutators
694 (methods beginning with 'set') can be used as keys.
700 <methodname>setTransport($transport)</methodname>: Set the
701 transport used to access the service; only POST is currently supported.
707 <methodname>getTransport()</methodname>: Get the current service transport.
713 <methodname>setEnvelope($envelopeType)</methodname>: Set the
714 request envelope that should be used to access the
715 service. Currently, supports the constants
716 <constant>Zend_Json_Server_Smd::ENV_JSONRPC_1</constant> and
717 <constant>Zend_Json_Server_Smd::ENV_JSONRPC_2</constant>.
723 <methodname>getEnvelope()</methodname>: Get the current request envelope.
729 <methodname>setContentType($type)</methodname>: Set the
730 content type requests should use (by default, this is 'application/json').
736 <methodname>getContentType()</methodname>: Get the current
737 content type for requests to the service.
743 <methodname>setTarget($target)</methodname>: Set the <acronym>URL</acronym>
744 endpoint for the service.
750 <methodname>getTarget()</methodname>: Get the <acronym>URL</acronym>
751 endpoint for the service.
757 <methodname>setId($id)</methodname>: Typically, this is the
758 <acronym>URL</acronym> endpoint of the service (same as the target).
764 <methodname>getId()</methodname>: Retrieve the service ID
765 (typically the <acronym>URL</acronym> endpoint of the service).
771 <methodname>setDescription($description)</methodname>: Set a
772 service description (typically narrative information
773 describing the purpose of the service).
779 <methodname>getDescription()</methodname>: Get the service description.
785 <methodname>setDojoCompatible($flag)</methodname>: Set a flag indicating
786 whether or not the SMD is compatible with Dojo toolkit. When
787 <constant>TRUE</constant>, the generated <acronym>JSON</acronym> SMD will
788 be formatted to comply with the format that Dojo's JSON-RPC client expects.
794 <methodname>isDojoCompatible()</methodname>: Returns the value of the
795 Dojo compatibility flag (<constant>FALSE</constant>, by default).
801 <methodname>addService($service)</methodname>: Add a service
802 to the map. May be an array of information to pass to
804 <classname>Zend_Json_Server_Smd_Service</classname>, or an
805 instance of that class.
811 <methodname>addServices(array $services)</methodname>: Add
812 multiple services at once.
818 <methodname>setServices(array $services)</methodname>: Add
819 multiple services at once, overwriting any previously set services.
825 <methodname>getService($name)</methodname>: Get a service by its name.
831 <methodname>getServices()</methodname>: Get all attached services.
837 <methodname>removeService($name)</methodname>: Remove a
838 service from the map.
844 <methodname>toArray()</methodname>: Cast the service map to an array.
850 <methodname>toDojoArray()</methodname>: Cast the service map
851 to an array compatible with Dojo Toolkit.
857 <methodname>toJson()</methodname>: Cast the service map to a
858 <acronym>JSON</acronym> representation.
864 <classname>Zend_Json_Server_Smd_Service</classname> has the following
871 <methodname>setOptions(array $options)</methodname>: Set
872 object state from an array. Any mutator (methods
873 beginning with 'set') may be used as a key and set via this method.
879 <methodname>setName($name)</methodname>: Set the service
880 name (typically, the function or method name).
886 <methodname>getName()</methodname>: Retrieve the service name.
892 <methodname>setTransport($transport)</methodname>: Set the
893 service transport (currently, only transports supported
894 by <classname>Zend_Json_Server_Smd</classname> are allowed).
900 <methodname>getTransport()</methodname>: Retrieve the current transport.
906 <methodname>setTarget($target)</methodname>: Set the <acronym>URL</acronym>
907 endpoint of the service (typically, this will be the
908 same as the overall SMD to which the service is attached).
914 <methodname>getTarget()</methodname>: Get the <acronym>URL</acronym>
915 endpoint of the service.
921 <methodname>setEnvelope($envelopeType)</methodname>: Set the
922 service envelope (currently, only envelopes supported
923 by <classname>Zend_Json_Server_Smd</classname> are allowed).
929 <methodname>getEnvelope()</methodname>: Retrieve the service envelope type.
935 <code>addParam($type, array $options = array(),
936 $order = null)</code>: Add a parameter to the
937 service. By default, only the parameter type is
938 necessary. However, you may also specify the order, as
939 well as options such as:
945 <emphasis>name</emphasis>: the parameter name
951 <emphasis>optional</emphasis>: whether or not the parameter is
958 <emphasis>default</emphasis>: a default value for the parameter
964 <emphasis>description</emphasis>: text describing the parameter
972 <methodname>addParams(array $params)</methodname>: Add
973 several parameters at once; each param should be an assoc
974 array containing minimally the key 'type' describing the
975 parameter type, and optionally the key 'order'; any other
976 keys will be passed as <varname>$options</varname> to
977 <methodname>addOption()</methodname>.
983 <methodname>setParams(array $params)</methodname>: Set many
984 parameters at once, overwriting any existing parameters.
990 <methodname>getParams()</methodname>: Retrieve all currently set parameters.
996 <methodname>setReturn($type)</methodname>: Set the return
997 value type of the service.
1003 <methodname>getReturn()</methodname>: Get the return value type of the
1010 <methodname>toArray()</methodname>: Cast the service to an array.
1016 <methodname>toJson()</methodname>: Cast the service to a
1017 <acronym>JSON</acronym> representation.
1025 vim:se ts=4 sw=4 et: