How to Use the DonorsChoose.org API with PHP and AJAX

While developing a Facebook app recently, I decided I wanted to list projects from DonorsChoose.org on the app's main page. Given their convenient API, this seemed like an easy way to support a good cause.

The DonorsChoose.org API for retrieving project data is simple and well documented. Project data is returned in JSON format; JSON itself is pretty simple, so I figured that retrieving and displaying the project list would be as well.

Conceptually, JSON is simple. So simple I'm not going to talk about it, in fact; I think you can learn everything you need to know about the format by skimming the examples page. And there is broad language support for it too - a quick glance at http://www.json.org/ proves that.

But therein lies the problem. It's so simple that nobody talks about how to actually use it. You're just supposed to know, I guess. For the JavaScript hackers of the world that's probably not a problem, but for us database geeks who hack PHP on the side it's different story. :)

After some poking around and old-fashioned hacking I discovered that it really is that simple, which is probably why nobody talks about it. So here, in a nutshell, is how to pull a project list from DonorsChoose.org using PHP and AJAX.

Version 1: Plain PHP

The simplest way to pull a project list from DonorsChoose.org and include it in your page is to request the list during the processing of your page and output the results like you would in any PHP page. For example:

<?php
$ch = curl_init();
# Change this to request the proposals you actually want
$url = 'http://api.donorschoose.org/common/json_feed.html?APIKey=DONORSCHOOSE';

# Use cURL to retrieve the list of projects from DonorsChoose.org
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_GETT, true);
$data = curl_exec($ch);

# Turn the data we got back into a hash of hashes
$dcInfo = json_decode($data, true);

# Uncomment to see everything you get back
#print_r($dcInfo);

# Pull out the list of proposals
$proposals = $dcInfo['proposals'];

# Find out how many we got back
$numProposals = count($proposals);

# Uncomment to see all the data available about the proposals retrieved
#print_r($proposals);

# Loop through the proposals and link the title of each to it
foreach ($proposals as $proposal)
{
    echo '<li><a href="' . $proposal['proposalURL'] . '">' . $proposal['title'] . "</a>\n";
}
?>
You can see this code in action here.

Version 2: PHP plus AJAX

The downside to requesting the project information directly in the PHP is that it delays the loading of your page. If instead you want to have the request made and the results shown after your page is loaded - i.e. using AJAX - you have to do two things:

  1. Create a PHP page that requests the data from DonorsChoose.org
  2. Add JavaScript to your page to call the PHP page you created and display the results

You can't request the data from DonorsChoose.org right in the JavaScript because, for security reasons, browsers don't allow JavaScript to make requests to domains other than the one from which the page originates.

The PHP to request the data from DonorsChoose.org looks very similar to our first implementation:

<?php
$ch = curl_init();
$url = 'http://api.donorschoose.org/common/json_feed.html?APIKey=DONORSCHOOSE';
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_GETT, true);
$data = curl_exec($ch);

echo trim($data);
?>
This simply retrieves the data from DonorsChoose.org and echoes the result. You'll want that trim() in there to eliminate some extra carriage returns you get at the start of the data.

The HTML to retrieve this data and display it looks like this:

<html>
    <head>
        <title>DonorsChoose.org JSON Test</title>
        <script>
        // Create the object we'll use to request the proposal
        // data from our PHP page
        if (window.XMLHttpRequest)
        {
            // code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        { 
            // code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }

        // Provide a function for the request object to call
        // when we get a response from the server
        xmlhttp.onreadystatechange=function()
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200)
            {
                // Parse the data from got from DonorsChoose.org
                // into an object we can use.  Proposals will
                // be in the 'proposals' member object
                var projList = JSON.parse(xmlhttp.responseText);
                for (var i in projList.proposals)
                {
                    var p = projList.proposals[i];
                    
                    // Add a link to each proposal to our div
                    document.getElementById('dc').innerHTML += '<a href="' + p.proposalURL + '">' + p.title + '</a><br/>';
                }
            }
        }

        // Call our PHP page
        try
        {
            xmlhttp.open("GET",'getDCList.php',true);
            xmlhttp.send();
        }
        catch (err)
        {
            alert(err);
        }
        </script>
    </head>
    <body>
        <h1>Top Projects From DonorsChoose.org</h1>
        <!-- We'll add the data we get from DonorsChoose.org to this div -->
        <div id="dc"></div>
    </body>
</html>
This requests the PHP page we created earlier and puts the results in the "dc" div. You can see this code in action here.

Feedback

Questions? Comments? Complaints?