Previous Page
Next Page

12.4. Exporting the Back End

Now that we've reviewed the functionality provided by the back-end Ticket class, let's look at what we need to do to export it to a JavaScript client. We have a number of options, including generating an XML file from the output of each Ticket method, creating chunks of HTML for each method, or having JSON encode the data. XML would work for an application like this, but there is no standard for describing PHP data structures in XML with which JavaScript automatically knows how to deal. An HTML chunk option is less than ideal because it would entail writing more PHP code and would limit flexibility. JSON is a great choice for an application such as this because code is available for PHP to encode its data structures into JSON, and JavaScript can directly evaluate the data it sends. In addition, JSON is a smaller encoding format than the other options, which helps keep our application running quickly. For these reasons, we will use JSON.

Now that we've decided that were going to use JSON, we need to figure out how we're going to make it accessible to the client. One option is to create a PHP page for each method; that page will look at the incoming POST data, transform it to PHP data types, call the method of the Ticket class, and then return its output formatted as JSON. An example of what this would look like for the login method is shown in Listing 12-3.

Listing 12-3. Login.php

1  <?php
2  require_once 'HTML/AJAX/Serializer/JSON.php';
3  require_once 'Ticket.class.php';
4
5  $rawin = file_get_contents('php://input');
6
7  $serializer = new HTML_AJAX_Serializer_JSON();
8  $in = $serializer->unserialize($rawin);
9
10 $ticket = new Ticket();
11
12 $out = $ticket->login($in->username,$in->password);
13
14 echo $serializer->serialize($out);
15 ?>

Lines 23 include the classes needed for this page. We're using the JSON serializer code from HTML_AJAX, but any PHP JSON library would work. Line 5 reads the raw POST input, with lines 7 and 8 using the JSON Serializer class to decode it into a PHP object. On line 10, we create a new Ticket instance, calling the login method on line 12. We then send the output to the client on line 14, serializing it into the JSON format. An example HTML page that can be used to test this login page is shown in Listing 12-4.

Listing 12-4. Login.html

1  <html>
2  <head>
3  <title>Login Tester</title>
4  <script type="text/javascript"
5  src="server.php?client=all"></script>
6  <script type="text/javascript">
7  var s = new HTML_AJAX_Serialize_JSON();
8  function callback(result) {
9    var profile = s.unserialize(result);
10   document.getElementById('target').innerHTML =
11     HTML_AJAX_Util.quickPrint(profile);
12 }
13 var options = {
14 args: s.serialize({username:'josh',password:'test2'})
15 };
16
17  function login() {

18   HTML_AJAX.grab('Login.php',callback,options);
19 }
20 </script>
21 </head>
22 <body>
23 <a href="javascript:login()">Run a test login</a>
24 <pre id="target">
25 </pre>
26 </body>
27 /html>

In Listing 12-4, we're again using the HTML_AJAX libraries to handle some of the AJAX grunt work. On lines 45, we include the HTML_AJAX JavaScript library. On lines 620, we define some functions to test making a JSON request to log in. On line 7, we create an instance of HTML_AJAX_Serialize_JSON; this instance will be used to transform JavaScript data to JSON strings and JSON strings back to JavaScript. Lines 812 define a callback function; this function will be called when our AJAX request is complete. It takes the resulting AJAX string and turns it into a profile object (line 9); it then uses a utility method to print its contents to a target element.

Lines 1315 set up an options object, which contains a JSON string that will be posted to the PHP page. Lines 1719 define the login function that makes the AJAX request. The request will be made to Login.php, calling the callback function when it's complete, and will pass in the serialized JSON string we set up in the options object. Line 23 provides us with a function to test it. When you run the login function, you will get output from the server that contains the user's profile, because that's what a successful login returns. An example is shown here:

user_id:1
username:josh
email:josh@bluga.net
loggedIn:true

This system works by sending the JSON-encoded string to the server; in this case, the string would be like so:

{"username":"josh","password":"test2"}

The server decodes that into a PHP object that looks like this:

object(stdClass)
  var 'username' => 'josh'
  var 'password' => 'test2'

The login method on the Ticket class is called; this method returns a profile array. This array is turned into a JSON string, which is sent back to the client. This JSON string looks like this:

{"user_id":"1","username":"josh","email":"josh@bluga.net","loggedIn":true}

This string is then decoded to a JavaScript object, where it can be used, or in the test case, where it is displayed in the target element.

We could follow this same pattern to create a PHP page for every Ticket method, but fortunately, we have a simpler option. HTML_AJAX provides code to automatically expose the Ticket class's methods in a similar fashion. On the PHP side, this functionality is provided through the HTML_AJAX_Server class. An example of exporting the Ticket class is shown in Listing 12-5.

Listing 12-5. Server.php

1 <?php
2 require_once 'HTML/AJAX/Server.php';
3 require_once 'Ticket.class.php';
4
5 $server = new HTML_AJAX_Server();
6 $server->registerClass(
7   new Ticket(),
8   'Ticket',
9   array(
10    'addUser',
11    'updateUser',
12    'listUsers',
13    'addTicket',
14    'updateTicket',
15    'getTicket',
16    'assignTicket',
17   'listUnassignedTickets',
18    'listAssignedTickets',
19    'listUpdatedTickets',
20    'login',
21    'isLoggedIn',
22    'currentUserId',
23    'logout'
24  )
25 );
26 $server->handleRequest();
27 ?>

This page is fairly simple. It creates a new HTML_AJAX_Server, registers the Ticket class with it, and then has the server handle requests to the page. Lines 23 include the required classes for the page. Line 5 creates the new HTML_AJAX_Server instance. Lines 625 register the class. Line 7 is the instance of the Ticket class, line 8 is the name to export it to JavaScript as, and lines 924 are an array of Ticket methods to export. These methods don't have to be specified; if they are not specified, PHP introspection is used to detect them, but if you're running on PHP 4, PHP can't detect the case of the functions; this can be annoying when we look at the JavaScript side of the equation because all the methods will be exported in lowercaseno matter what they look like in the PHP code.

On the JavaScript side, HTML_AJAX provides a stub class that has all the methods that were exported. When you call one of these methods, an AJAX call is made against the server. When working with this setup, it's important to remember that you don't have a PHP object being remotely controlled through JavaScript. Instead, you have an automatic wrapping of a JavaScript method to an AJAX call. Each method call takes an HTTP request, which means you have a new instance of the PHP Ticket class for each response; this process is shown in Figure 12-3.

Figure 12-3. Data flow of multiple requests to PHP using HTML_AJAX's generated JavaScript proxy


To create this JavaScript class, you simply need to add another include to your HTML file. The syntax is Server.php?stub=Name. This includes the JavaScript class definition. When you create an instance of this class, you pass it in a single parameter, which is the callback object to use. Matching methods on this callback object will be used to handle the response of the AJAX request. For example, if you call ticket.login, the login method on the callback object will be called when the request is complete. An example of calling the login method using HTML_AJAX's auto class export is shown in Listing 12-6.

Listing 12-6. LoginStub.html

1  <html>
2  <head>
3  <title>Login Tester</title>
4  <script type="text/javascript"
5  src="server.php?client=all"></script>
6  <script type="text/javascript"
7  src="server.php?stub=Ticket"></script>
8  <script type="text/javascript">
9  var callback = {
10    login: function (result) {
11      document.getElementById('target').innerHTML
12      = HTML_AJAX_Util.quickPrint(result);
13    }
14 }
15
16  var ticket = new Ticket(callback);
17
18  function login() {
19    ticket.login('josh','test2');
20  }
21  </script>
22  </head>
23  <body>
24  <a href="javascript:login()">Run a test login</a>
24  <pre id="target">
25  </pre>
26  </body>
27  </html>

Using the stub class helps reduce the complexity of our JavaScript code because it makes the AJAX request look much like a normal AJAX call. JSON serializing and unserializing happens automatically, so you only deal with JavaScript data types. The big changes from Login.html are as follows: including the Ticket stub (lines 78), making the callback a hash (lines 914), and using a remote stub object to make the AJAX call (lines 16 and 19). The other item to note is that the code doesn't worry about any of the data serialization, letting us move to another format at any time without changing any application code.


Previous Page
Next Page