15.1. Using Atlas with PHPTo use Atlas with PHP, you must first create a PHP web page. The page that we'll create to demonstrate Atlas with PHP contains an HTML text box and Atlas xml-script to add autocomplete functionality to the text box. However, to add the Atlas functionality we need, the Atlas client libraries must be loaded into the page. To do this, create a new folder in your web site named ScriptLibrary/Release. (For example, if your web site is at C:\Atlas\, create a folder named C:\Atlas\ScriptLibrary\Release.) Access the libraries using the Windows Start menu (see the beginning of this chapter) and copy the files Atlas.js, AtlasCompat.js, and AtlasCompat2.js (release versions) into the new ScriptLibrary/Release folder.
The page must load the main Atlas library (Atlas.js). Depending on the browser type, one or two additional compatibility libraries might also be required on the page. The code in 15-1 shows a PHP page that includes Atlas functionality. (When you create this page, you must name it with a .php extension, of course.) The page shows how to use PHP code to conditionally load an Atlas .js library depending on browser type. For example, if the user agent string contains "opera", the code loads the AtlasCompat.js library. If the user agent string contains "safari", both the AtlasCompat.js and AtlasCompat2.js libraries are loaded. Example 15-1. A PHP page that loads Atlas libraries
In the xml-script for Example 15-1, the AutoCompleteService.php file is the web service invoked by the autocompletion behavior. This pseudoweb service .php file must contain the logic for returning a list of matching elements. The method called to fetch names is GetVendors(). It will look roughly like the following code. Like the ASP.NET version, this PHP code uses SQL Server 2005 Express Edition and the AdventureWorks sample database. (Naturally, you could use any other database and sample data.) function GetVendors($prefixText, $count) { if (!is_string($prefixText)) { return; } $count = ($count > 0) ? min($count, 10) : 10; ini_set('magic_quotes_sybase', 1); $prefixText = addslashes($prefixText); ini_set('mssql.secure_connection', 1); $db = mssql_connect('(local)\SQLEXPRESS'); mssql_select_db('AdventureWorks', $db); $result = mssql_query( "SELECT Name FROM Purchasing.Vendor WHERE Name LIKE '$prefixText%'"); $results = array(); while ($row = mssql_fetch_row($result) && count($results) < $count) { $results[] = $row[0]; } mssql_close($db); return $results; } A bit more complicated is the code that processes the request to the "web service." As with the ASP.NET version, the PHP script file is called with a suffix of /js. When the PHP program detects this suffix, it must create a proxy script and make it available to the client. The JavaScript code for the proxy looks like the following (assuming that the script resides in http://localhost/Atlas/): var AutoComplete = new function() { this.path = "http://localhost/Atlas/AutoCompleteService.php"; this.appPath = "http://localhost/Atlas/"; Sys.Net.ServiceMethod.createProxyMethod(this, "GetVendors", "prefixText", "count"); Sys.Net.ServiceMethod.createProxyMethod(this, "processRequest"); } The path data must be determined dynamically in code and then injected into the page, but only if the requested URL ends in js. The following PHP code shows how this dynamic generation can be done: $path = $_SERVER['REQUEST_URI']; if (substr($path, strlen($path) - 2) == 'js') { $applicationRoot = dirname($_SERVER['SCRIPT_NAME']); $pathWithoutProxy = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; $pathWithoutProxy = substr($pathWithoutProxy, 0, strlen($pathWithoutProxy) - 3); $pathWithoutProxy = addslashes($pathWithoutProxy); $documentRoot = 'http://' . $_SERVER['SERVER_NAME'] . $applicationRoot . '/'; $documentRoot = addslashes($documentRoot); echo "var AutoComplete = new function() { this.path = \"$pathWithoutProxy\"; this.appPath = \"$documentRoot\"; Sys.Net.ServiceMethod.createProxyMethod(this, \"GetVendors\", \"prefixText\", \"count\"); Sys.Net.ServiceMethod.createProxyMethod(this, \"processRequest\"); } "; }
The remainder of the script AutoCompleteService.php takes care of the situation when the proxy is not generated, but a web service method is called instead (using the proxy). Tracing the HTTP traffic while running the AutoComplete extender within Atlas and ASP.NET 2.0 shows that the framework calls the web service script (one the user entered three characters or more in the text field) and appends ?mn=<MethodName> to the URL. The prefix text and the maximum number of results to return are submitted in JSON format in the body of the request. In our example, the data expected from the client consists of JSON data with two entries: prefixText and count. This data is extracted from the HTTP request using $GLOBALS['HTTP_RAW_POST_DATA'] and then decoded using the JSON.php library. In the next step, the GetVendors() method is called to determine all suitable database entries for the given prefix. This resulting data is then encoded back into JSON and returned. (It's trivial to encode data in JSON format manually, but since we are already using the JSON library, why bother investing too much effort into our own code?) This is what the processRequest method looks like, which performs all of these tasks: function processRequest() { $path = $_SERVER['REQUEST_URI']; if (substr($path, strlen($path) - 2) == 'js') { $applicationRoot = dirname($_SERVER['SCRIPT_NAME']); $pathWithoutProxy = 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; $pathWithoutProxy = substr($pathWithoutProxy, 0, strlen($pathWithoutProxy) - 3); $pathWithoutProxy = addslashes($pathWithoutProxy); $documentRoot = 'http://' . $_SERVER['SERVER_NAME'] . $applicationRoot . '/'; $documentRoot = addslashes($documentRoot); echo "var AutoComplete = new function() { this.path = \"$pathWithoutProxy\"; this.appPath = \"$documentRoot\"; Sys.Net.ServiceMethod.createProxyMethod(this, \"GetVendors\", \"prefixText\", \"count\"); Sys.Net.ServiceMethod.createProxyMethod(this, \"processRequest\"); } "; } else if (!isset($_GET['mn']) || $_GET['mn'] != 'GetVendors') { exit(); } else { $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); $postData = trim($GLOBALS['HTTP_RAW_POST_DATA']); if (strlen($postData) > 0) { $argsAsParams = $json->decode($postData); if (isset($argsAsParams['prefixText']) && isset($argsAsParams['count'])) { $returnValue = $this->GetVendors( $argsAsParams['prefixText'], $argsAsParams['count']); echo $json->encode($returnValue); } } } } This completes the PHP class that implements the web service and proxy generator for the AutoComplete extender. All that is left to do is to instantiate the class when the file is loaded and call the processRequest() method. 15-2 shows the complete code, with that final task as the last two lines of the program Example 15-2. The PHP Atlas compatible pseudo web service
As you can see, the code can get to be a bit more complicated than the corresponding code in ASP.NET. But the important point is that you can take advantage of Atlas even though you may not be using ASP.NET 2.0. See Figure 15-1 for the result in the browser; apart from the PHP URL, you can't see any obvious difference from the ASP.NET 2.0 version of the example. Figure 15-1. The same example as before, but this time using PHP
|