Calling PUT and DELETE on RESTful PHP services with Prototype.js
So I was asked to create a RESTful web service in PHP. No problem. I was asked to create a PHP client that connects to it through cURL. No problem. I was asked to create an AJAX interface to administer it. Problem.
The problem wasn’t the same origin policy, as the AJAX interface was to run on the same server as the service. The problem was implementing the HTTP methods.
I use Prototype.js for all of my Javascript coding. I’d recommend it to anyone, especially for AJAX as it makes your life a doddle. The basic syntax of an AJAX request using Prototype looks like this:
ajax = new Ajax.Request('test.php',{ method: get, onSuccess: function(xmlHTTP) { $('response').update(xmlHTTP.responseText); } });
There’s a host of options for making various types of request, but that’s the gist of it. The problem with this, however, is that not all browsers support the PUT and DELETE methods, which in REST are used to update and delete records, respectively. As such, Prototype’s Ajax objects don’t try and send an XmlHttpRequest object using PUT or DELETE.
It turns out that these two methods are implemented using POST as a proxy. It then tells the web service the method you really wanted in $_POST[‘_method’]. This means that to implement calls through AJAX, where your code would have looked something like this:
if($_SERVER["REQUEST_METHOD"] == "GET") { echo("This looks like a GET request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "POST") { echo("This looks like a POST request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "PUT") { echo("This looks like a PUT request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "DELETE") { echo("This looks like a DELETE request to me!"); }
It would now need to look like this:
if($_SERVER["REQUEST_METHOD"] == "GET") { echo("This looks like a GET request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "POST" && !isset($_POST['_method'])) { echo("This looks like a POST request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "PUT" || $_POST['_method'] == 'put') { echo("This looks like a PUT request to me!"); } else if ($_SERVER["REQUEST_METHOD"] == "DELETE" || $_POST['_method'] == 'delete') { echo("This looks like a DELETE request to me!"); }
I’m guessing that any data you’re trying to send to PUT that would normally be read in from php://input would have to by hidden in the _POST array somewhere. More experimentation required methinks!