RESTful Service and Client with PHP and AJAX
... and a little mod_rewrite :-)
Here I'm going to show you how you can implement a RESTful interface using exclusively JavaScript code on the client side, and PHP on the server side. In between them we are going to use minimal Apache's mod_rewrite for some URI manipulation.
All the source code for this example as well as a working version of it can be found here on the Labs section. And here's a ZIP archive containing the same files for download.
Files
Let's get started by listing the files that will be part of the solution:
myResource.php - Contains the PHP implementation of the service. In this case I have chosen to include the code for different methods in the same file.
client.html and client.js - Markup and JavaScript code for the client that will consume our service. On this example you'll see different methods being invoked and different responses being handled.
.htaccess - Contains the rule that translate the RESTful URL and redirects the request to our PHP implementation. The file htaccess.txt contains a copy of the hidden file's content for easy viewing.
RESTful URI's
Now, the URI's we want for this example have the following form:
/api/myResource/[RESOURCE_ID]
For example:
http://ccswf.ca/labs/restfulPhpAjax/api/myResource/1234
That means that if we want to get information for the resource number 1234 we need to perform a GET request to that URI. If we wanted to delete that same resource we would issue a DELETE HTTP request and if we wanted to list all resources we would omit the id part. You get the idea.
So the rule that interprets that URL is inside the .htaccess file and looks like this:
RewriteRule ^api/(myResource)(/\d{0,8})?$ serviceImpl/$1.php
It basically tells Apache to let our PHP file handle all requests involving that resource. The regular expression allows for the id to be optional.
The actual parsing of the URL will be made in the PHP code. Let's see how that is done.
Service Implementation (Server-Side)
The property that allows us to read the original URI is REQUEST_URI in the $_SERVER global object . In our example we are only interested on the id part of the string so that's what we extract:
$parts = preg_split("/\//", $_SERVER["REQUEST_URI"]);
$resourceId = $parts[count($parts) - 1];
The other thing we have to take care of with PHP is detecting the HTTP method invokes. The property for that is called REQUEST_METHOD. And here it is in action:
if($_SERVER["REQUEST_METHOD"] == "GET") {
...
} else if($_SERVER["REQUEST_METHOD"] == "DELETE") {
...
}
Our service only supports methods GET and DELETE, but any HTTP method can be used.
Some HTTP requests like POST allow data to be passed to the server. The easiest way to access that data from PHP is by opening the php://input pseudo-file. Like this:
$input = file_get_contents("php://input");
And finally, after we do our stuff -like deleting the resource- we send back a HTTP response code to the client. That is done by using the built-in header function. Here's an example:
header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found");
On that line the protocol taken from the $_SERVER global object, although we know it will probably be a version of HTTP. In this particular case, the response code we have chosen to return is a 404 code, as in "couldn't find a resource with the given ID". That response will be decoded on the client side.
Client Implementation (Service Consumer)
Let's jump to the client implementation to see how those methods are actually invoked. In a nutshell, what we do is use the AJAX technique to send requests to the URI. The JavaScript object that will do all that for us is the XMLHttpRequest object.
So in our single client.js Javascript file you will find something similar to the following code.
var req = new XMLHttpRequest();
...
req.open("PUT", "api/myResource/1234");
req.send("Some resource data");
On that snippet we call the PUT method on a specific resource identifier, passing along some text as data. What's been cut out from there is the actual handling of the response, which will look something like this:
req.onreadystatechange = function() {
if(req.readyState == 4) {
if(req.status == 200) {
// Ok
var returnedData = req.responseText;
} else if (req.status == 404) {
// Not found
var statusInfo = req.statusText;
} else if (req.status == 501) {
// Not implemented, this should not happen
}
}
}
Notice how the different response codes are handled explicitly and how the response data is obtained from responseText property.
So that is pretty much all you need to know in order to create a neat client-server interaction RESTstyle. Hope you liked it. Don't be afraid to add your questions or comments.
See you next time!
Attachments:
restfulPhpAjax.zip (2.5 KB)
HTML templates with JavaScript and external XML
Hello all and welcome to the C+C Software Factory blog.
On this, my first post, I would like to demonstrate a technique for storing XHTML templates on external files and applying them using standard JavaScript and DOM methods.
There are two main files involved in this example:
- myTemplate.xml - contains the common structure for all the pages that are instances of the template. In this case the layout consists of a table with header, footer, left column and right column cells.
- myPage.html - represents an entry point and an instance of the template. It contains the markup to be relocated within the corresponding region of the template.
For clarity, I separated the CSS and JavaScript code into two files named myPage.css and myPage.js.
So basically what we have is two separate markups -layout and content- that we want to merge, customize and display. That work is done by the applyTemplate() function invoked when myPage.html is accessed.
In a nutshell, here's what the applyTeplate() function does:
- Load the external XML document containing the template
- Import the template nodes into the main HTML document - without displaying it
- Move the original content (nodes) into the corresponding region of the layout
- Display the final layout by appending the imported node to the body element
Finally these are the most important snippets of the code:
myPage.html (entry point, template instance):
<body> <div id="rightContent"> <h1>Lorem ipsum dolor sit amet,</h1>
...
</div>
...
</body>
myTemplate.xml
<table xmlns="http://www.w3.org/1999/xhtml" class="layout">
... <tr> <td colspan="2"><div id="headerContainer">...</div></td> </tr> <tr> <td><div id="leftContainer">...</div></td> <td><div id="rightContainer"></div></td> </tr> <tr> <td colspan="2"><div id="footerContainer">...</div></td> </tr> ... </table>
myPage.js
function applyTemplate() { // our main function
// first thing, remove current content from document
var content = document.body.removeChild(document.getElementById("rightContent"));
// bring in the external template
var templateXml = getXml("myTemplate.xml");
// import template into main document
var templateNode = document.adoptNode(templateXml.firstChild);
// customize header
templateNode.getElementsByTagName("div")[0].childNodes[0].nodeValue = "Custom Page Header";
// insert template into document's body
document.body.appendChild(templateNode);
// put back custom content into the template
var totalNodes = content.childNodes.length;
for(var i = 0; i < totalNodes; i++) {
document.getElementById("rightContainer").appendChild(content.firstChild);
}
}
...
Some considerations:
- getXML() is a simple XHR call, in this case, a synchronous call (included with full source code)
- adoptNode() is a standard DOM method not implemented by IE so a substitute implementation is needed (included)
- Outer elements defined in the template XML must have the xmlns (name space) attribute to be imported propperly
- IE requires the table element defined in the template to contain a tbody element, this has no effect on other browsers
- IE requires certain attributes like class, style, for, colspan to be renamed, that's taken care of by the replacement adoptNode function
Acknowledgements:
- The original importNode() replacement was taken (and modified) from here
You can find the full source code attached to this post. A running example can be found at http://ccsoftwarefactory.com/labs/xmlJsTemplate
Thank you and stay tuned for more JavaScript tips and tricks!
Attachments:
xmlJsTemplate.zip (5.6 KB)