Ajax using jQuery and PHP

There are quite a few examples on the web detailing how to retrieve data from a web service using Ajax and jQuery, there are also a few examples how to create a web service in PHP. Unfortunately when I recently tried to implement something for a client I had certain amount of difficulty which was caused by the web page with the ajax being located on one web server and the PHP web service located on another.

In most scenarios both service and web page would be located on the the same server. Most examples explaining how to retrieve data from a remote service will tell you that due to browser security it is not possible to use JSON, instead  JSONP must be used this. The code below is a Ajax request to retrieve a list of people whose birthday occurs for a particular month. If successful the data is displayed in a simple table. In the HTML part of the code I have declared an empty DIV with the id “birthdays”. The table with results is appended to this DIV. This works fine if the call is to a service on the same server, if the service resides on another server then a minor change to the javascript is required. So the code below

$.get("birthdays.php?month=12",
	function(data){
        // First Create the table and column headings
		$('#birthdays').append('<div class="bdaydiv" id="bdaydiv"><table class="bdTable"id="bdayTable"><tr><td>Name</td><td>Date</td><tr></table></div>');
        // For each item returned.
		$.each(data,function(i,birthdays){
		$('#bdayTable').append('<tr class="rowresult" id="rowresult"><td>'+birthday.name+'</td><td>' + birthday.date+'</td></tr>');
		});
	}, "json") // json specifies the data will be returned in JSON format
	.success(function() {
	// Place any functionlity that you want upon success here
	}
	.error(function( jqXHR, textStatus, errorThrown) {
	// These lines are handy if you are trying to debug
	console.log("error " + textStatus);
	console.log("errorThrown " + errorThrown);
	console.log("incoming Text " + jqXHR.responseText);
	console.log("contents Text " + jqXHR.contents);
	console.log("get XMLHttpRequest= "+XMLHttpRequest.responseText);
	})
	.complete(function() {// Place any function that you want upon completion here
});

becomes

$.get("http:\\www.example.com\birthdays.php?month=12&callback=?",
	function(data){
        // First Create the table and column headings
		$('#birthdays').append('<div id="bdaydiv"><tableid="bdayTable"><tr><td>Name</td><td>Date</td><tr></table></div>');
        // For each item returned.
		$.each(data,function(i,birthdays){
		$('#bdayTable').append('<tr id="rowresult"><td>'+birthday.name+'</td><td>' + birthday.date+'</td></tr>');
		});
	}, "json") // json specifies the data will be returned in JSON format
	.success(function() {
	// Place any functionlity that you want upon success here
	}
	.error(function( jqXHR, textStatus, errorThrown) {
	// These lines are handy if you are trying to debug
	console.log("error " + textStatus);
	console.log("errorThrown " + errorThrown);
	console.log("incoming Text " + jqXHR.responseText);
	console.log("contents Text " + jqXHR.contents);
	console.log("get XMLHttpRequest= "+XMLHttpRequest.responseText);
	})
	.complete(function() {// Place any function that you want upon completion here
});

The change is only minor an involves the addition of callback=? to the URL. This all fairly straight forward and there are plenty of examples of how to do this on the web. The bit that is not always explained too well is what happens on the server side. The service is a simple php service to return a list of bithdays for a particular month in JSON format.

<?php
$month = $_GET['month'];

/* connect to the db */
$link = mysql_connect('localhost','username','password') or die('Cannot connect to the DB');
mysql_select_db('db_name',$link) or die('Cannot select the DB');

/* grab the posts from the db */
$query = /* query to retrieve birthdays for a particular month from the database
$result = mysql_query($query,$link) or die('Bad query: '.$query);

/* create an array to hold the results */
$brithdays = array();
	if(mysql_num_rows($result)) 
	{
		while($row = mysql_fetch_assoc($result)) 
		{
			$birthdays[] = array('name'=>$row['name'],'date'=>$row['date']);
		}
		/* Need to first set the content type */
		header('content-type: application/json; charset=utf-8');
		/* JSON encode the array */
		echo json_encode($birthdays);
	}
?>

The above code works fine if it resides on the same domain. If it is going to sit on a different domain we need to make a few changes.

<?php
$month = $_GET['month'];
$callback = $_GET['callback'];

/* connect to the db */
$link = mysql_connect('localhost','username','password') or die('Cannot connect to the DB');
mysql_select_db('db_name',$link) or die('Cannot select the DB');

/* grab the posts from the db */
$query = /* query to retrieve birthdays for a particular month from the database
$result = mysql_query($query,$link) or die('Bad query: '.$query);

/* create an array to hold the results */
$brithdays = array();
	if(mysql_num_rows($result)) 
	{
		while($row = mysql_fetch_assoc($result)) 
		{
			$birthdays[] = array('name'=>$row['name'],'date'=>$row['date']);
		}
		/* Need to first set the content type */
		header('content-type: application/json; charset=utf-8');
		/* JSON encode the array */
		echo $callback."(".json_encode($birthdays).")";
	}
?>

I have highlighted the lines that have changed. The first change involves retrieving the value of “callback” that was passed to it. For those wondering where the value for “callback” comes from when we are  not setting one in the  javascript call.

$.get("http:\\www.example.com\birthdays.php?month=12&callback=?"

The answers is the value is automatically generated by the jQuery $.get function and appended to the URL for you. It expects to see the function in the JSON encoded result it not the function will not work and if you are debugging in Firebug you will see an error stating a callback function consisting of a bunch of numbers could not be called, you will then spend many hours on google trying to understand what is happening. Hopefully this article will prevent a few people from having to go through that.

No related posts.

Related posts brought to you by Yet Another Related Posts Plugin.

This entry was posted on Monday, April 16th, 2012 at 5:27 pm and is filed under Code, javascript, PHP. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply