Note:This is an article I wrote on 11/18/2003. It was originally published at PHPPatterns. I thank Harry for letting me use his site as a platform. I plan to update this article in the near future with new developments in the world of Ajax and PHP/XUL. This article is introduces some of the technical aspects of getting XUL clients hooked up with PHP, based on the authors practical experience of building XUL user interfaces. If you don't know what XUL is and need an introduction, the article XUL: Rendering GUI's with PHP may be a good place to start. It gives a good introduction to XUL, its background and its uses. So, you have looked at XUL and think it's pretty cool stuff. But, you hate programming with javascript and are stuggling to leverage the power of your favorite scripting language, PHP. There are ways around this, but the minefield of the Gecko security model is a little to much work to figure out. Well, hopefully after reading this, you will be able to create PHP applictions that can be supplemented by the use of a XUL interface, or even a standalone XUL application that uses PHP as a server backend. To start off with, we need a simple XUL file that contains a form. This form could consist of anything, but for this example, I will be using a simple Login form that is familiar in many web applications. Some of the XUL has been left out to save space. The entire file is included in the attachment. The XUL file The form really doesn't have much to offer in the way of beauty, but it gets the job done. Notice that the Sign in button references the loginCmd listed in the <commandset></commandset> section above. Keeping your javascript commands out of the main XUL body helps promote readabilty and reuseability. <!-- Client.xul --> <window id="phpServer-Communication-test" title="PHP Server Communication Test" orient="horizontal" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script src="js/main.js" type="application/x-javascript"></script> <script src="js/server.js" type="application/x-javascript"></script> <commandset> <command id="loginCmd" oncommand="doLogin()"/> </commandset> <vbox flex="1" align="center" pack="center" style="background-color:#444"> <grid style="background-color:#999; padding:40px; border-top: 2px solid #bbb; border-left: 2px solid #bbb; border-bottom: 2px solid #555; border-right: 2px solid #555"> <columns> <column/> <column/> </columns> <rows> <row> <label value="Username"/> <textbox id="loginUser" style="width:10em"/> </row> <row> <label value="Password"/> <textbox id="loginPass" style="width:10em" type="password"/> </row> <row> <spacer/> <button label="Sign in" command="loginCmd"/> </row> </rows> </grid> </vbox> </window> Not too hard to read - we've all seen HTML that makes less sense. The PHP Server Rather than being extraordinarily complicated, our PHP server simply echos the value's passed to it to the screen as well as some text to prove it's the real thing (a call to the date function). <?php session_name('XULSession'); // Set session name session_start(); echo "Server Time is: ".date("m/d/Y H:i:s")."\n"; echo "\$_POST = \n"; print_r($_POST); echo "\$_GET = \n"; print_r($_GET); // Watch these... echo "\$_COOKIE = \n"; print_r($_COOKIE); echo "\$_SESSION = \n"; print_r($_SESSION); if ( $_GET['username'] == 'root' && $_GET['password'] == 'topsecret' ) { $_SESSION['username'] = $_GET['username']; $_SESSION['password'] = $_GET['password']; } ?> Note the <pre> tags aren't needed around the print_r's because javasript does not squish whitespace like browsers do. Pay attention (when running this example yourself) to what's happens to the $_COOKIE and $_SESSION variables above. The session name (XULSession) turns up in the $_COOKIE array. In other words the XUL client is doing the same as a browser does between requests (via the XMLHttpRequest object - see below). Also if you enter the username as "root" password as "topsecret" these will show up in the $_SESSION array on the next request (you need to "login" a two times to see this). In other words you can use PHP's sessions to lock the remote XUL client out of your PHP application until a valid username and password is provided. Users will still have the remote client running (unlike normal browser clients where's you'd probably send an HTTP redirect to an HTML login form) but as long as you keep the real Business Logic in PHP, requiring a valid session to execute it, there should be no real issues here. The XUL client will simply be "dumb and pretty" unable to do any harm. The Javascript File The real action takes place in the main.js file. Here's an excerpt containing the doLogin function.  /* main.js */ function doLogin() { var username = document.getElementById('loginUser').value; var password = document.getElementById('loginPass').value; req = new phpRequest(); req.add('action','doLogin'); req.add('username',username); req.add('password',password); var response = req.execute(); alert(response); } Running the script Ok, so now that all the files are in place, we are going to run the script. Starting with the blank form, simply enter in a sample username and password.    Login to XUL   Next, his the 'Sign in' button and witness the response from the server. Connection Established   How it works After the "Sign in" button is clicked, the doLogin method in main.js is called. In it, the username and password have been pulled from the XUL form via the Javascript DOM. For more information on the methods available via DOM, take a look at some of the links in the references at the end of this article. After we have pulled in the username and password into scope, a new 'phpRequest' object is instantiated. The phpRequest is a javascript object that takes care of the nasty details of connecting and talking to a PHP server. More on that later in the article. The add() function simply takes a key/value pair that contains data that will be sent to the php script. After all key/value pairs have been added to the request, the execute method is called and the request is actually made to the the server. The entire HTTP response body is returned by the execute method. The response is then echoed to the screen to provide feedback that our method actually worked. A word about security Now, before you get to excited about how easy that is, I need to explain about some of the limitations this has. The javascript security model limits what can be connected to. That means that if you upload this XUL file and javascript file to a php server, your server MUST also be on the same server and the path to the server must be relative. In other words: XUL URL: http://some.server/xul/xulform.xul Server URL: /xul/server/server.php (must be relative) The second way to connect to a remote server would be to install your XUL package into your local chrome directory. When you install the package locally, you can connect to any server via an absolute URL. More information about the javascript security model can be found on the web. The phpRequest object The phpRequest object is where all the magic happens. It provides a programmer friendly interface to the implementation details of the XMLHttpRequest object that actually makes the call to the php page. The Javascript: const SERVER_URL = "/xul/server.php"; //Start phpRequest Object function phpRequest() { //Set some default variables this.parms = new Array(); this.parmsIndex = 0; //Set the server url this.server = SERVER_URL; //Add two methods this.execute = phpRequestExecute; this.add = phpRequestAdd; } function phpRequestAdd(name,value) { //Add a new pair object to the params this.parms[this.parmsIndex] = new Pair(name,value); this.parmsIndex++; } function phpRequestExecute() { //Set the server to a local variable var targetURL = this.server; //Try to create our XMLHttpRequest Object try { var httpRequest = new XMLHttpRequest(); }catch (e){ alert('Error creating the connection!'); return; } //Make the connection and send our data try { var txt = "?1"; for(var i in this.parms) { txt = txt+'&'+this.parms[i].name+'='+this.parms[i].value; } //Two options here, only uncomment one of these //GET REQUEST httpRequest.open("GET", targetURL+txt, false, null, null); //POST REQUEST EXAMPLE /* httpRequest.open("POST", targetURL+txt, false, null, null); httpRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); */ httpRequest.send(''); }catch (e){ alert('An error has occured calling the external site: '+e); return false; } //Make sure we received a valid response switch(httpRequest.readyState) { case 1,2,3: alert('Bad Ready State: '+httpRequest.status); return false; break; case 4: if(httpRequest.status !=200) { alert('The server respond with a bad status code:' +httpRequest.status); return false; } else { var response = httpRequest.responseText; } break; } return response; } //Utility Pair class function Pair(name,value) { this.name = name; this.value = value; } Javascript's object model is a little screwy. Instead of defining a 'class' in php, you create functions and then link them together. That is what is happening in the phpRequest function. Several variables are set including the server URL that is defined by a constant variable on the first line of the program. After the variables are defined, the literal function names are assigned to local variables. When that is done, they become callable methods inside the object. There are several other ways to do this within javascript, please refer to the javascript core specifiacation for details. The phpRequest maintains an internal array of Pair objects. Because javascript does not have the same array support that php does, a workaround is needed to create a key/value array. The Pair object performs this task very well. The method where the action really happens in the phpRequestExecute method. It contains the code that helps us to connect to a php server from our javascript. The javascript object that allows us to connect to another script via HTTP is the XMLHttpRequest object. It is an internal javascript object that can be used to return XML (or HTML) documents from an external source. More information about the XMLHttpRequest object can be found on the XULPlanet website. After the XMLHttpRequest object has successfully been instantiated, the url is simply created by looping over the internal array of key/value pairs. Now, you can use either GET or POST to send data to the server. I have included code for both methods. The same URL is passed, but there is one difference. When you send a POST request, you have to set the content type to be 'application/x-www-form-urlencoded' so the web server you are sending it to will know that you are sending a POST request. There are more tricks if you need to send larger amounts of data, but they are beyond the scope of this article. After you set the url, you must call the XMLHttpRequests send method. This is what actually sends the request to the server. Following the code, after a response from the server is received, it is stored in the XMLHttpRequest's responseText variable and available for use.  Conclusion This is a good start. We've got the building blocks in place. If there is enough interest, I can explain in my next article about how to wrap up data from PHP (such as the results of a database query) in our own XML dialect and access it from XUL. Code for this article More Info Create Web applets with Mozilla and XML - has some tips on "inlining" XUL in XHTML. The Mozilla Amazon Browser - if you haven't seen it already, be amazed... XUL Planet