Dynamic Web Development
Fall, 2011
Christopher Sung
Interactive Telecommunications Program, NYU
Class 11 - Web Service Integration, Mashups, and Facebook Apps

Contents:


Providing a Web Service   [top]
Last week, we saw how to integrate content from a foreign site into web pages using client-side code (JavaScript) that interacts with an API from the foreign site. We can now turn this around and look at how we can be the ones to provide content via an API. The API needn't be particularly complicated, and it's even easier if the user base (e.g. the ones to write code that makes requests of your service) is small. In the following code, I have made the entries from the favorite sites demos available as a web service. It can be accessed at a specific URL on our stage server, and it outputs either in XML or JSON format:

$format = strtolower($_GET["format"]);
$sort_by = strtolower($_GET["sort"]);

if ($format=='json')
{
  $arr_main = array();
  
  $SqlStatement = "SELECT id, title, url, description, votes FROM class05_table2
    ORDER BY votes desc, title";
  $result = mysql_query($SqlStatement,$connection);
  if (!$result) die("Error " . mysql_errno() . " : " . mysql_error());
  while ($row = mysql_fetch_array($result,MYSQL_NUM))
  {  
    $arr_local = array(
      'id' => $row[0],
      'title' => htmlspecialchars($row[1]),
      'url' => htmlspecialchars($row[2]),
      'description' => htmlspecialchars($row[3]),
      'votes' => $row[4]
    );
    
    array_push($arr_main,$arr_local);
  }
  
  $data = json_encode($arr_main);

  # Tell the browser what type of content to expect
  header("Content-type: application/json");

  # Now send our JSON
  print $data;

}
else
{
  $data = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<response>\n";

  $SqlStatement = "SELECT id, title, url, description, votes FROM class05_table2
    ORDER BY votes desc, title";
  $result = mysql_query($SqlStatement,$connection);
  if (!$result) die("Error " . mysql_errno() . " : " . mysql_error());
  while ($row = mysql_fetch_array($result,MYSQL_NUM))
  {  # Add this row to our XML data
    $data .= "<o id=\"$row[0]\" ";
    $data .= "title=\"".htmlspecialchars($row[1])."\" ";
    $data .= "url=\"".htmlspecialchars($row[2])."\" ";
    $data .= "description=\"".htmlspecialchars($row[3])."\" ";
    $data .= "votes=\"".htmlspecialchars($row[4])."\" ";
    $data .= "></o>\n";
  }

  # Finish our data
  $data .= "</response>\n";

  # Tell the browser what type of content to expect
  header("Content-type: text/xml");

  # Now send our XML
  print $data;

}
  • Fav Sites Web Service (XML) | Fav Sites Web Service (JSON) | Source Code

    Then, to access the data from the web service, we call it the same way we would any other API. In this case, we are populating the list of sites the same way we did on the server-side using PHP, but now we use jQuery to get the sites from the web service in JSON format and then fill our unordered list in HTML:

    <script language="javascript">
    
    function load()
    {
      url = 'http://itp.nyu.edu/~cs220/dwd/class11-rest-server.php?format=json&sort=p';
    
      // Get the data from the web service and process
      $.getJSON(url,function(data){
          
        // Create list entry for each item found
        $.each(data, function(i,item){
        
          var local_text = '<li><a target="newSite" href="' + item.url + '">' + item.title + '</a><br>';
              local_text += item.votes + ' votes · <i>' + item.description + '</i>';
              
          $('<li></li>').html(local_text).appendTo('#sitelist');
          
        });
     
      });
    }
    </script>
    </head>
    <body onload="load()">
    
  • End User Page Using the Service | Source Code


    Web Service Integration in PHP   [top]
    Just as web services can be integrated on the client-side using JavaScript, they can also be used on the server-side with PHP. Instead of using a framework like jQuery to gather the info on the client-side, you can use PHP's cURL library to access the same data on the server-side:

    #########################################################
    # Get the most popular music videos at Yahoo Music
    #########################################################
    $urlValue = 'http://us.music.yahooapis.com/video/v1/list/published/popular';
    $urlValue .= '?response=main&format=json&appid=[app key]';
    
    $json_text = "";
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $urlValue);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         
    $json_text = curl_exec($ch);
    curl_close($ch);
    
    #########################################################
    # Convert JSON to PHP struct
    #########################################################
    $obj = json_decode($json_text);
    
    Just as our received data was parsed into a structure by jQuery, the same data can be converted into PHP objects using PHP's JSON functionality. Objects in PHP use the "->" operator to descend within a structure (similar to JavaScript's '.' metaphor). So to get at the data, we can say:
    $list = $obj->Videos->Video;
    
    print "<p><b>Top Videos on Yahoo! Music</b><br>\n";
    for($i=0; $i<count($list); $i++)
    {  
      $item_id = $list[$i]->id;
      $title = $list[$i]->title;
      $rank = $list[$i]->ItemInfo->ChartPosition->this;
    
      # Write some HTML here
    }
    
  • Yahoo Music Video Demo | Source Code
  • Sample JSON from Yahoo Music API
  • Yahoo Music API

    The main benefit of parsing on the server-side is that the actual content can be indexed by search engines and thus easily found by users on the web (this does not happen with content created by web services on the client-side). In addition, if you have relevant data in your database, you can correlate some of that info with the content drawn from the web service.

    The main drawback is that your server now has to do more work because it has to obtain and serve the content from the web service.


    jQuery UI   [top]
    jQuery UI is the official jQuery user interface library. It provides interactions, widgets, effects, and theming for creating Rich Internet Applications. Much of the client-side functionality one sees on the web is either based upon or mimicked in this library.

    Like jQuery, we can simply include a public version of the library, along with some base CSS. Then, it's up to you how best to incorporate its functionality into your interface. Need a Netflix type sortable queue?

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js">
    <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css" type="text/css" />
    
    <script type="text/javascript">
    
    $(function() {
      $( "#sortable" ).sortable({
        revert: true
      });
      $( "#draggable" ).draggable({
        connectToSortable: "#sortable",
        helper: "clone",
        revert: "invalid"
      });
      $( "ul, li" ).disableSelection();
    });
    
    </script>
    
    <body>
    <ul id="sortable" class="ui-sortable">
      <li class="ui-state-default">Item 1</li>
      <li class="ui-state-default">Item 2</li>
      <li class="ui-state-default">Item 3</li>
      <li class="ui-state-default">Item 4</li>
      <li class="ui-state-default">Item 5</li>
    </ul>
    </body>
    

    Since jQuery goes well with server-side interaction, it's only natural we can combine PHP functionality with jQuery and jQuery UI to create an autocomplete widget. The client code is:

    <script type="text/javascript">
    
    $(function() {
    
      $( "#country" ).autocomplete({
        source: "http://itp.nyu.edu/~cs220/dwd/class11-countrysearch.php",
        minLength: 2
      });
      
    });
    
    </script>
    </head>
    <body>
    <div class="ui-widget">
      <label for="country">Country: </label>
      <input id="country" />
    </div>
    </body>
    
    while on the server side, we can use the SQL LIKE clause to look for countries that match the typed chars in the text field:
    $term = $_GET['term'];
    
    $arr_main = array();
      
    $SqlStatement = "SELECT id, name FROM music101_country WHERE id>1 AND name like '%$term%' LIMIT 10";
    $result = mysql_query($SqlStatement,$connection);
    while ($row = mysql_fetch_array($result,MYSQL_NUM)) {  
      $arr_main[] = array(
        'id' => $row[0],
        'value' => htmlspecialchars($row[1]),
      );
    }
    $data = json_encode($arr_main);
    
    # Now send our JSON
    header("Content-type: application/json");
    
    print $data;
    

    Introduction to Mashups   [top]
    Mashups are when you combine two or more web services to form an application. One of the most common components of a mashup is Google Maps because it can be combined with any other web service that provides location-based or geocoded data. Any listing of physical structures (resturants, shops, toilets, wi-fi hotspots, et al) can easily be plotted on a Google Map as long as location data is provided for each listing.

    In the following example, we use Yelp's API for Business Search to obtain listings that lie within a specified Google map. The main input parameters to the Yelp search are a keyphrase ("sushi" or "bike shop") and the latitude and longitude of the bounding box encompassed by a Google Map:

    function showResults(query) {
    
      // Clear existing markers
      map.clearOverlays();
    
      // Figure out the URL to call at Yelp
      var mapBounds = map.getBounds();
      
      var url = "http://api.yelp.com/" +
        "business_review_search?"+
        "callback=?" +
        "&term=" + encodeURI(query) + 
        "&num_biz_requested=10" +
        "&tl_lat=" + mapBounds.getSouthWest().lat() +
        "&tl_long=" + mapBounds.getSouthWest().lng() + 
        "&br_lat=" + mapBounds.getNorthEast().lat() + 
        "&br_long=" + mapBounds.getNorthEast().lng() +
        "&ywsid=" + YWSID;
    
      // Get the data from the web service and process
      $.getJSON(url,
        function(data){
        
          // Create marker for each business found
          $.each(data.businesses, function(i,biz){
          
            createMarker(biz, new GLatLng(biz.latitude, biz.longitude), i);
            
          });
          
      });
    }
    
    // Creates a marker for the given business and point
    function createMarker(biz, point, markerNum) {
    
      var infoWindowHtml = generateInfoWindowHtml(biz);
      
      var marker = new GMarker(point, icon);
      
      map.addOverlay(marker);
      
      GEvent.addListener(marker, "click", function() {
        marker.openInfoWindowHtml(infoWindowHtml, {maxWidth:400});
      });
      
      // automatically open first marker
      if (markerNum == 0)
        marker.openInfoWindowHtml(infoWindowHtml, {maxWidth:400});
    }
    
  • Google-Yelp Mashup Demo
  • Yelp
  • Yelp API Overview & Getting Access
  • Yelp API Documentation
  • Yelp Examples

    In the code above, we use jQuery to make the request to the Yelp API, and for each business we get back in the resulting JSON data, we create a new marker on the Google Map.

    Mashups Ad Nauseum
    With so much content now freely available, it's not surprising that there's a plethora of mashups out there. A good resource for keeping track of developments in this area is:

  • programmableweb.com

    The Facebook API   [top]
    With the increasing popularity of Facebook and its user base, the powers that be at Facebook decided to create a framework in which one can work with many aspects of Facebook. With the launch of the Facebook social graph, developers have the capability to create applications that operate inside and outside of Facebook, leveraging the site's resources, or to interact via script.

    Consider the following code:

    <?php
    
    $entry = array(
      'subject' => 'This is a test',
      'message' => 'Here is some test text',
    );
    
    /*
    # Follow their auth docs to learn what the access token
    # is for the Facebook entity of interest
    http://developers.facebook.com/docs/authentication/
    
    This token is for a fan page:
    http://www.facebook.com/pages/ActiveBass/43761154835
    */
    $entry['access_token'] = $sm_keys['facebook']['access_token_ab'];
    
    # Grab the Facebook client
    # https://github.com/facebook/php-sdk
    require_once 'fbclient/facebook.php';
    
    # Create the client using application keys
    $facebook = new Facebook(array(
      'appId'  => $sm_keys['facebook']['keys']['main'],
      'secret' => $sm_keys['facebook']['keys']['secret'],
      'cookie' => true,
    ));
    
    try {
      $facebook->api('/me/notes', 'POST', $entry);
      echo "Posting note -- success\n";
    }
    catch (FacebookApiException $e) {
      echo "Posting note -- failed\n";
      echo $e->getMessage()."\n";
    }
    

    A Facebook application was created at https://developers.facebook.com/apps. Using the keys for this app, a client for interacting with Facebook is created using their SDK for PHP. OAuth tokens were obtained for each page for which the developer is an admin, as outlined at http://developers.facebook.com/docs/authentication/.

    Using a given access token for a certain fan page, we can auto-create a note using the Graph API.

    Facebook Core API and Docs
  • Facebook Developer Documentation
  • Facebook PHP SDK
  • Facebook Graph API

    Facebook Apps

  • How to Build a Facebook App
  • Guide to Integrating Facebook into Mobile Apps


    The Twitter API   [top]
    Similarly, Twitter provides developers with the ability to create applications that interact with Twitter's functionality via script. Simply register a new app using your Twitter account, obtain your app's access keys, and off you go. There are a variety of code libraries to facilitate integration with their API.

    Consider the following code:

    # Grab a Twitter lib
    # https://dev.twitter.com/docs/twitter-libraries#php
    # this is one is from http://classes.verkoyen.eu/twitter_oauth
    require_once('twitter.php');
    		
    $twitter = new Twitter($sm_keys['twitter']['keys']['main'], $sm_keys['twitter']['keys']['secret']);
    	
    # set tokens  
    $twitter->setOAuthToken($sm_keys['twitter']['tokens']['oauth_token']);  
    $twitter->setOAuthTokenSecret($sm_keys['twitter']['tokens']['oauth_token_secret']);
    
    $tweet = "Test: the random number is: ".mt_rand(1,1000000);
       
    # this is where it tweets!
    try {
      $res = $twitter->statusesUpdate($tweet);
      echo "posted\n";
    }
    catch(TwitterException $e) {
      echo $e->getMessage()."\n";
    }
    

    In this case, given the app keys, and OAuth tokens, we make a simple call to the library, which takes one argument: the tweet. It then posts it to Twitter via the API.

    Using a given access token for a certain fan page, we can auto-create a note using the Graph API.


    URL Rewriting and Friendly Links   [top]
    Another topic that might help in your web trevails is understanding how to create arbitrary links to your content and scripts, and how these can be mapped using special software that resides in the web server. The concept is called url rewriting and it allows you to have control over the display of url links. For example, the url:

    http://mysite.com/blog_entry.php?i=56
    
    while functional, doesn't really tell you much about the content of the page. However:
    http://mysite.com/DWD-Is-Putting-Me-To-Sleep--b56
    
    is a bit more descriptive. The trick here is figure out how to take the latter URL and map it to the former. In this case, we see that after the "title" in the latter, there two dashes and then the numerical id of the blog entry. Thus, we can come up with a regular expression that says if find two dashes, followed by a "b", followed by a number, go to the blog_entry.php script and put the number in query string for "i". There's an actual syntax you can use to describe this:
    ^(.*)--b(\d{1,})$   blog_entry.php?i=$2
    
    On the Apache web server, there is a module called mod_rewrite which allows you to create and apply these mappings. In our case, we defined these mappings in a file called .htaccess. .htaccess files can control many aspects of how content is served in Apache. For us, we can put the .htaccess file in the directory where we want the rewriting to occur (typically the root directory of the website but it can be in any folder with relevant content), and put in something like the following, which controls content in our "dwd" directory:
    RewriteEngine On
    RewriteBase /~netId/dwd/
    RewriteRule ^(.*)--b(\d{1,})$   blog_entry.php?i=$2 [L]
    
    The RewriteBase directive tells the web server to strip this path off of the URL before applying the rules that follow it. The [L] after our rule means "last", as in this is the last rule to apply if you find a match. If we wanted more rules, say, to guide a user to a specific page about an image (maybe for a photography or portfolio site) as oppoed to a blog entry, we could have the format:
    http://itp.nyu.edu/~netId/dwd/Central-Park-at-Night--i22
    
    map to:
    http://itp.nyu.edu/~netId/dwd/image_entry.php?i=22
    
    with the rewrite rule being:
    RewriteRule ^(.*)--i(\d{1,})$   image_entry.php?i=$2 [L]
    
    and thus our .htaccess file changing to:
    RewriteEngine On
    RewriteBase /~netId/dwd/
    RewriteRule ^(.*)--b(\d{1,})$   blog_entry.php?i=$2 [L]
    RewriteRule ^(.*)--i(\d{1,})$   image_entry.php?i=$2 [L]
    
  • Unrewritten Musician List Demo | Source Code
  • Rewritten Musician List Demo | Source Code
  • Apache mod_rewrite Documentation

  • Home  ·  Syllabus  ·  Submissions  ·  Resources
    © 2003-2013. All rights reserved.