Handling JSON request in PHP

I’ve been working with PHP and jQuery AJAX quite a bit lately. Along with sending form data to PHP page through AJAX, I’ve written restful web services in PHP that receive data in JSON format.

In general when you are sending data through jQuery AJAX to PHP, you don’t have to specify a contentType. Depending on your type ‘GET’ or ‘POST’, PHP will nicely wrap your content into either the $_POST or $_GET global arrays. When you don’t specify a contentType the default contentType is taken as application/x-www-form-urlencoded; charset=UTF-8’.

Following is the request headers from an AJAX call without contentType specified,

GET /ajax-php/api.php?firstname=Abijeet&lastname=Patro HTTP/1.1 
Host: localhost:8081 
Connection: keep-alive 
Cache-Control: no-cache Pragma: no-cache 
Accept: */* 
X-Requested-With: XMLHttpRequest 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer:http://localhost:8081/ajax-php/index.php
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8,fr;q=0.6

To further test this, I set up the following PHP code on my server,

<?php
$get=$_GET;
$post=$_POST;
$app_json=json_decode(file_get_contents('php://input');
$response=array();
$response['GET']=$get;
$response['POST']=$post;
$response['JSON']=$app_json;
echo json_encode($response);
die();

The response that for the above request case was,

{
  "GET": {
    "firstname": "Abijeet",
    "lastname": "Patro"
  },
  "POST": [],
  "JSON": null
}

If we put the jQuery AJAX type property as ‘POST’ we will have the following request header,

POST /ajax-php/api.php HTTP/1.1 
Host: localhost:8081 
Connection: keep-alive 
Content-Length: 32 
Cache-Control: no-cache 
Pragma: no-cache 
Origin: http://localhost:8081
X-Requested-With: XMLHttpRequest 
Content-Type: application/x-www-form-urlencoded; 
charset=UTF-8 
Accept: */* 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 
Referer: http://localhost:8081/ajax-php/index.php
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8,fr;q=0.6

Nothing much changes. The action is specified as POST and the data is no longer a part of the request header. The response from the server is following,

{
  "GET": [],
  "POST": {
    "firstname": "Abijeet",
    "lastname": "Patro"
  },
  "JSON": null
}

Obviously, PHP has no issues parsing content of type – application/x-www-form-urlencoded; charset=UTF-8. As soon as it sees that contentType, it checks the action and packs the data nicely into either $_GET or $_POST.

Let’s now talk about JSON data. In general, restful web services accept data of type JSON. When sending data via JSON the contentType for jQuery AJAX is application/json; charset=UTF-8

This is the request header,

POST /ajax-php/api.php HTTP/1.1 
Host: localhost:8081 
Connection: keep-alive 
Content-Length: 42 
Cache-Control: no-cache 
Pragma: no-cache 
Origin: http://localhost:8081
X-Requested-With: XMLHttpRequest 
Content-Type: application/json; charset=UTF-8
Accept: */* 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 
Referer: http://localhost:8081/ajax-php/index.php
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8,fr;q=0.6

When PHP receives this data and looks at the content type, it’s not quite sure how to process it, so it leaves it alone. In this case the action – ‘POST’ or ‘GET’ doesn’t matter. You’ll notice that $_POST or $_GET both, are empty arrays. Now, it’s up to you to read this data and parse it.

<?php
$app_json=json_decode(file_get_contents('php://input'));

The code above, reads the data from PHP’s input stream. Since we have passed a JSON string, we decode it, which converts it to a PHP array and stores it in $app_json. If the data you send is not in a correct JSON format, $app_json will have false.

When we echo our response, we get the following on the client side,

{
  "GET": [],
  "POST": [],
  "JSON": {
    "firstname": "Abijeet",
    "lastname": "Patro"
  }
}

I set up a small project to illustrate what has been written here. You can find it over on my GitHub page

Continue reading “Handling JSON request in PHP”

Tree view based file explorer for the web using jQuery.

This post assumes that the reader has a basic understanding of PHP, jQuery and jQuery $.post

Recently I had to implement a windows-esque tree view based file explorer for one of my projects at work. I ended up using this wonderful jQuery plugin to help me. In this blog I’ll be going through some basic code to get it working using PHP on the server side.

To whet your appetite, here’s what we’ll be achieving in this blog post – A complete tree view based file explorer that feeds from a folder on the server’s file system.

File tree view

So let’s get started!

To be able to render a proper tree using the aciTree plugin, we’ll need to send JSON from server in the following format –

[
  {
    "id": "folder_1",
    "label": "ThisisFolder1",
    "inode": true,
    "open": false,
    "icon": "folder",
    "branch": [
      {
        "id": "sub-item_x",
        "label": "ThisisFileX",
        "inode": false,
        "icon": "file"
      },
      {
        "...": "..."
      },
      {
        "...": "..."
      }
    ]
  },
  {
    "id": "file_1",
    "label": "ThisisFile1",
    "inode": false,
    "icon": "file"
  },
  {
    "...": "..."
  },
  {
    "...": "..."
  }
]

Here’s the list of things that we’ll be doing –

  1. Server Side Code
  2. HTML
  3. JavaScript/jQuery code to communicate with the server.
  4. Basic event handling for the aciTree plugin.

1. Server side code

Let’s move onto the PHP code. Our job is to read the files from the specified folder and return a JSON structure that resembles what’s shown above. If you look closely you’ll observe that the JSON above is basically an array of objects of with properties as – id, label, inode, icon, open

The following class is exactly similar to that of the class received via JSON. We’ll be returning an array of NodeList objects from the server.

<?php
/**
 * Represents each node in the aci tree jquery plugin
 * 
 * @author abijeet
 */
class NodeList {
    public $id, $label, $inode, $open, $icon, $branch;
    private $openIfBranch;

    /**
     * Constructor for NodeList
     *
     * @param string $label
     *          Label of the node
     * @param boolean $open
     *          If this is a branch, should it be open
     * @param string $icon
     *          Icon for the node
     */
    public function __construct($label, $open, $id, $icon = '') {
        if ($id) {
            $this->id = $id;
        }
        $this->label = basename($label);
        $this->open = false;
        $this->openIfBranch = $open;
        $this->icon = $icon;
        $this->inode = false;
    }

    public function setBranch($branch) {
        $this->branch = $branch;
        $cntBranch = count($branch);
        if ($cntBranch > 0) {
            $this->inode = true;
            $this->label .= ' [' . $cntBranch . ']';
        }
        $this->open = $this->openIfBranch;
    }
}

Now to read the list of files and folders from a location on the server –

<?php
/**
 * Function that given a path, returns an array of nodeList
 * This can then be converted to a json format.
 * 
 * @param $path Path
 *          of the folder from which to retrieve
 * @return multitype:NodeList Returns the json tree
 */
function jsonForResTree($path) {
    $dirArray = getAllFilesAndFolders($path);
    $nodeArray = array ();
    $node = '';
    $cnt = count($dirArray);
    for($i = 0; $i < $cnt; ++ $i) {
        $node = new NodeList($dirArray[$i], false);
        if (is_dir($dirArray[$i])) {
            // Recursion - It's a folder, get the array of nodeList for it.
            $nodeList = jsonForResTree($dirArray[$i]);
            // Add it as branch
            $node->setBranch($nodeList);
        }
        $nodeArray[] = $node;
    }
    return $nodeArray;
}

/**
 * Gets all files and folders from the specified path
 * 
 * @param unknown $path
 *          Path of the folder from where files and folders are to be retrieved
 * @return multitype:
 */
function getAllFilesAndFolders($path) {
    if (! is_dir($path)) {
        return array ();
    }
    $path = $path . DIRECTORY_SEPARATOR . '*';
    return glob($path, GLOB_NOSORT);
}

Some code to handle the request that we will be making from the client side and then echoing the output in JSON format –

<?php
if (! empty($_POST['method'])) {
    // Do some check before handling the POST data.
    $methodToCall = $_POST['method'];
    ob_clean();
    // Call the method requested from the client side.
    $result = call_user_func($methodToCall);
    die(json_encode($result));
}

/**
 * Function that is call by the JQUERY post.
 * 
 * @return multitype:NodeList
 */
function getJsonTree() {
    // Folder Path from where we are going to show the tree view.
    $pathToGetAciTree = './cakephp';
    $jsonTree = jsonForResTree($pathToGetAciTree);
    return $jsonTree;
}

Okay so we have the PHP code in place. Next order of things –

  1. Server Side Code
  2. HTML
  3. JavaScript/jQuery code to communicate with the server.
  4. Basic event handling for the aciTree plugin.

2. HTML

The following HTML goes inside the body tag-

<!-- Scripts and CSS to be loaded. This will be avaliable when you download aciTree plugin --> 
<link href="css/aciTree.css" rel="stylesheet" type="text/css" /> 
<link href="css/demo.css" rel="stylesheet" type="text/css" /> 

<!-- Loading jQuery --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> 
<!-- Loading the aciTree plugin --> 
<script type="text/javascript" src="js/jquery.aciPlugin.min.js"></script> 
<!-- Loading the aciTree core--> 
<script type="text/javascript" src="js/jquery.aciTree.core.js"></script> 
<!-- Loading the aciTree selectable plugin --> 
<script type="text/javascript" src="js/jquery.aciTree.selectable.js"></script> <!-- The div that will contain the ACI Tree --> 
<div id="fsTree"></div> 
<button id="btnGetTreeView">Get Tree View</button> 
<button id="btnRefreshTreeView">Refresh Tree View</button> 
<div id="currStatus"></div>

Next, the JavaScript/jQuery to get the aciTree plugin working. This should be put inside the document’s ready handler –

3. jQuery code to communicate with the server

$currStatus = $('#currStatus');
// Makes the ajax call and fetches the json for the resource tree.
$('#btnGetTreeView').click(function() {
  $("#fsTree").aciTree({
    ajax: {
      type: 'POST',
      url: 'index.php',
      data: {
        // Notice that this is the method name that
        // we wish to call on the server side.
        'method': 'getJsonTree'
      }
    }
  });
});

// Refreshing the tree view - Destroy and recreate
$('#btnRefreshTreeView').click(function() {
  var api = $('#fsTree').aciTree('api');
  api.unload(null, {
    success: function() {
      this.ajaxLoad(null);
      // Triggering the click handler of the Get Tree View button.
      // This will make the ajax call again and bind the tree...
      $('#btnGetTreeView').trigger('click');
      $currStatus.text('');
    }
  });
});

4. Event handling for the aciTree plugin

And finally a simple event handler for the aciTree that is triggered whenever a node in the tree is selected –

// ACI Tree - event handler.
$('#fsTree').on('acitree', function(event, aciApi, item, eventName, opt) {
  switch (eventName) {
    case 'focused':
    case 'selected':
      // Fired when an item in the tree is selected.
      if (item) {
        $currStatus.text('Selected - ' + item.context.innerText);
      }
  }
});

You can find the whole code here and a working copy of the project here.

Passing JavaScript object to ASP.NET web service or method

I recently came across a question on StackOverflow, where the author was having trouble calling a JSON based web service from his ASPX page using jQuery. He was passing a user defined JavaScript object. I decided that I would quickly put a project together describing how to do so, for my future reference, and for anyone else who needs help. Here is my original answer on StackOverflow. I’ll be offering a higher level of explanation here in the post.

Below is the web method that we’ll be calling, in my ASPX page code behind. Note that a web method has to be declared as static,

[System.Web.Services.WebMethod]
public static Contact getContact(Contact cnt)
{ 
    cnt.name="Abijeet Patro"; 
    cnt.phone="Blah Blah";
    return cnt;
}

The user defined object that you pass through JavaScript has to have the same properties as the user defined object on the server. Say for example that you were passing the following from JavaScript –

var cnt = { name : 'Hello', phone :'Hello' };

The object we defined in JavaScript has two properties, name and phone in lower case letters.

This is exactly similar to the class defined on the server

public class Contact 
{
    public string name {get;set;}
    public string phone {get;set;}
}

Note that the properties in the class have to be public

Now we’ll see how to call this web method from our ASPX page,

$(document).ready(function () {
    var cnt = {name:'Hello',phone:'Hello'};
    $.ajax({
        type: "POST",
        url: "/Default.aspx/getContact",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: JSON.stringify({'cnt':cnt}), // Check this call.
        success: function (data) {
            debugger;
        }
    });
});

For an explanation of the options used here check jQuery ajax API documentation,

I’ll be discussing two noteworthy things,

1. Sending data to the server

Data (data) contains the object we will be sending to the server. Before we send the object to the web method, we have to ensure that we convert the object into a JSON format. We can do this by calling JSON.stringify. This javascript method is supported in all modern browsers*. The values that you pass to JSON.stringify have to be similar to what I have specified here. The name of the object we are passing to the server is named as 'cnt' in single or double quotes. This also has to be exactly same as the variable name being accepted by the web method.

public static Contact getContact(Contact cnt)

2. Specifying what to connect to

The url specifies the web method or web service that we wish to call. If we were calling an ASP.NET based web service, we’d just have to change the url to /Default.asmx/getContact. Note that the name of the method that we wish to call is concatenated to the end of the web service path.


Now let’s see everything in action using Fiddler, a nifty network monitoring tool.

You’ll notice the call, with the request data sent to the server, and the response that is received from the server. If the call succeeds the success function of jQuery ajax is called. The server returns data as a JSON object and we can access it using the d property of the object. ASP.NET adds the property by default as of .NET Framework 3.5 to protect you from JSON hijacking.

Data sent to the server

Response from the server

So that’s basically it, if you have any doubts, ping me through the comment section. You’ll find the source code for the application here.

JSON.stringify is not supported by Internet Explorer 7 by default. To add this function to it, add JSON2.js to your page.