Recipe 13.16. Integrating with JavaScript


13.16.1. Problem

You want part of your page to update with server-side data without reloading the whole page. For example, you want to populate a list with search results.

13.16.2. Solution

Use a JavaScript toolkit such as Dojo to wire up the client side of things so that a particular user action (such as clicking a button) fires off a request to the server. Write appropriate PHP code to generate a response containing the right data. Then, use your JavaScript toolkit to put the results in the page correctly.

Example 13-59 shows a simple HTML document that loads Dojo and the code in Example 13-60. Example 13-60 is the JavaScript glue that sends a request off to the server when the Search button is clicked and makes sure the results end up on the page in the right place when they come back. Example 13-61 is the PHP code that does the searching and sends back a JSON-formatted response.

Basic HTML for JavaScript integration

<!-- Load Dojo --> <script type="text/javascript" src="/books/3/131/1/html/2//dojo.js"></script> <!-- Load our JavaScript --> <script type="text/javascript" src="/books/3/131/1/html/2//search.js"></script> <!-- Some input elements --> <input type="text"  /> <input type="button"  value="Search"/> <hr/> <!-- Where the output goes --> <div ></div> 

JavaScript integration glue

// When the page loads, run this code dojo.addOnLoad(function() {     // Call the search() function when the 'go' button is clicked     dojo.event.connect(dojo.byId('go'), 'onclick', 'search'); }); function search() {     // What's in the text box?     var q = dojo.byId('q').value;     // Send request to the server     // The url should be to wherever you save the search page     dojo.io.bind({ 'url': '/search.php',                  'content': { 'q': q },                  // Type of the response                  'mimetype': 'text/json',                  // Function to call when the response comes                  'load': showResults }); } // Handle the results function showResults(type, results, evt) {     var html = '';     // If we got some results...     if (results.length > 0) {         html = '<ul>';         // Build a list of them         for (var i in results) {             html += '<li>' + dojo.string.escapeXml(results[i]) + '</li>';         }         html += '</ul>';     } else {         html = 'No results.';     }     // Put the result HTML in the page     dojo.byId('output').innerHTML = html; }

PHP to generate a response for JavaScript

<?php // Initialize JSON require_once 'Services/JSON.php'; $json = new Services_JSON(); $results = array(); $q = isset($_GET['q']) ? $_GET['q'] : ''; // Connect to the database from Chapter 10 $db = new PDO('sqlite:/usr/local/data/zodiac.db'); // Do the query $st = $db->prepare('SELECT symbol FROM zodiac WHERE planet LIKE ? '); $st->execute(array($q.'%')); // Build an array of results while ($row = $st->fetch()) {     $results[] = $row['symbol']; } // Splorp out all the anti-caching stuff header("Expires: 0"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); // Add some IE-specific options header("Cache-Control: post-check=0, pre-check=0", false); // For HTTP/1.0 header("Pragma: no-cache"); // The response is JSON header('Content-Type: application/json'); // Output the JSON data print $json->encode($results); ?>

13.16.3. Discussion

The HTML in Example 13-59 is pretty minimal by design. All that's there are a few elements and calls to load external scripts. Separating JavaScript from HTML is good development practice'similar to segregating your presentation logic and your business logic on the server side. The first <script/> tag in Example 13-59 should point to wherever you've installed Dojo. The second should point to wherever you've put the code in Example 13-60. That handful of JavaScript functions provides the bridge between the HTML elements in Example 13-59 and the server-side code in Example 13-61. The first call to dojo.addOnLoad( ) tells the web browser, "When the page is finished loading, run the JavaScript code that tells the web browser, "When the go button is clicked, run the search( ) function."

A lot of JavaScript programming is event based'along the lines of setting up rules like "when such-and-such happens, run this function." A web page studded with JavaScript does not have a strictly procedural flow from start to finish. Instead, it presents the user with lots of possibilities'clicking buttons, typing stuff in text boxes, clicking on links, and so on. Your JavaScript code usually sets up various event handlers'functions that run in response to clicking, typing, and other events.

In Example 13-60, the search( ) function uses Dojo's dojo.io.bind( ) function to send a request back to the server, passing whatever's in the text box as the q query string parameter. The other arguments to dojo.io.bind( ) indicate that a JSON response is expected, and when the request arrives, it should be passed to the showResults( ) function.

The showResults( ) function, in turn, takes those results and builds an HTML list out of them. Once the list has been built up, it sets the content of the output <div/> to contain that HTML.

Example 13-61 is the familiar part of this triumvirate. It's very similar to any "search the database for some stuff based on user input" PHP script, except for how it returns results. Instead of printing HTML, it uses the techniques described in 13.15 to send back an uncacheable JSON response.

Writing applications that rely on JavaScript-based client-side activity requires a different programming paradigm than your typical PHP application. Instead of thinking about how to generate entire dynamic pages, you have to think about how to generate bits of dynamic data that client-side logic can display or manipulate in convenient ways. A toolkit such as Dojo gives you a robust platform on which to build such applications. It abstracts away many of the messy practicalities of JavaScript programming'cross-browser incompatibilities, the guts of asynchronous I/O, and other housekeeping.

There are PHP-centric JavaScript toolkits available, such as PEAR's HTML_Ajax and xajax. They aim to let you write PHP functions and methods and then call them easily from JavaScript, taking care of the tedious glue of mapping particular JavaScript functions to particular PHP functions. While these toolkits provide PHP-focused convenience, they do so at the cost of JavaScript-focused robustness. While either HTML_Ajax or xajax can be useful and convenient in quickly tying some server-side PHP code to client-side logic, they are not built to handle applications that are designed from the ground up as client focused.

That said, comfortably intersecting PHP and JavaScript is a problem for which many folks are actively developing solutions. Easier paths undoubtedly will emerge after these words are written.

13.16.4. See Also

13.15 details sending JSON responses. Dojo is at http://www.dojotoolkit.org/, xajax at http://www.xajaxproject.org/, and HTML_Ajax at http://pear.php.net/package/HTML_Ajax. "Getting Rich with PHP" (http://talks.php.net/show/tek06) explores the performance implications of responding to lots of JavaScript-based requests. Other JavaScript toolkits include script.aculo.us (http://script.aculo.us/), Prototype (http://prototype.conio.net/), and the Yahoo! User Interface Library (http://developer.yahoo.com/yui/index.html).




PHP Cookbook, 2nd Edition
PHP Cookbook: Solutions and Examples for PHP Programmers
ISBN: 0596101015
EAN: 2147483647
Year: 2006
Pages: 445

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net