Create a Mashup from Scratch

 

In this tutorial we are going to create a search Mashup which searches for books and shows the category of the search string. We will cover the basics required for making of any mashup.Let’s get started !!

Tutorial Structure

  • What is a Mashup?
  • Setting up workspace.
  • Tutorial

What is a Mashup?

A mashup is a nothing but a web application which borrows services from a 3rd party for a specific purpose. These services can be easily integrated with the project. Mashups have many benefits -

  • Fast development
  • Low cost
  • Less testing time
  • Scalable

A mashup allows fast development since we do not need to create the same service from scratch. In this tutorial we are going to create a search mashup which searches for books and shows the categories of the search string using external services.

In this tutorial we will use Google book api for searching the books and semantic hackers signature api to for getting the dimensions.

Setting up work space.

  • Requirements
    1. Basic knowledge of PHP.
    2. Basic knowledge of jQuery and jQuery UI.
    3. Basic knowledge of working with HTML and CSS.
  • Libaries
    1. jQuery – you can get it from here.
    2. jQuery UI – you can get it from here. In this tutorial we will be using start theme..
    3. Zend Google Data API – you can get it from here.
  • Difficulty – advance
  • Estmated Time for Completion- 1 hour

Step 1

We will start off by creating our directory structure.

Here -

  • js folder will contain our javascript files.
  • css folder will contain our main css file and jQuery UI files.
  • img folder consist of images we will use(optional).
  • lib folder contains our php files which will interact with the other services.

Step 2

First we will start off by creating our php file that will get services from the semantic hacker. We will create a php file in the library folder and name it as semantichacker.php .

Step 3

To use any REST services, we need to have a token or key for authentication and working with the api. Semantic hacker is no different. To get the key -

  • Goto to semantic hacker’s website and Register.
  • After successful registration, you will get a token similar to this – ed4xxxxx.
  • This will be our key used for working with the API.

Step 4

First of all to work with web services in PHP, we will need to enable the curl extension. To do this we will -

  • Goto to php.ini in the php diretory and remove the semicolon of ;extension=php_curl.dll to enable the extension.
  • Copy the libeay32.dll and ssleay32.dll to the system32 (on windows and restart the system ;) or set the path on the corresponding OS.
  • CURL is installed.

Step 5

Now enter the following code in the semantichacker.php .


$search = $_POST['search_text'];

$url ="http://api.semantichacker.com/edxxxxx/signature?content=$search&showLabels=true";

Here first we will get our search string through the POST array and insert it in the url. Here this url will serve as therequest for our search string. To understand more about what is happening in the url we will break it into parts.

  • http://api.semantichacker.com/ this is the base url for api request.
  • edxxxxx is the token used for authentication.
  • signature defines that we are interested in the dimensions.
  • content=$search, here we append the search string
  • showLabels=true, here we are requesting that there should be string for results instead of code.

Step 6

Now we are going to work with Curl to send a Http request to the semantic hacker. For that we type in the following code.


function get_data($path){

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$path);

curl_setopt($ch, CURLOPT_FAILONERROR,1);

curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);

curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);

curl_setopt($ch, CURLOPT_TIMEOUT, 15);

$retValue = curl_exec($ch);

curl_close($ch);

return $retValue;

}

Here we have created a function which returns the response data. First we have initiated the curl using curl_init(), then we will pass the parameters including the url. Finally we will execute it and reurn the value.

Note: Curl only passes the request through the proxies, it does not parse or manipulate any data.

Step 7

We will get a response similar to this one, upon our request


9044B06D269F5D28099F4D54E3FEDF5E 93F725A07423FE1C889F448B33D21F46</pre>

<pre>signature odp_2007_l1_1.7k text/plain

93F725A07423FE1C889F448B33D21F46 2009-12-21T14:23:57+00:00 2.0

This is actually a xml response but Curl does not reconize it, so we need a xml parser to parse the information.

Step 8

Actually the xml response looks like.


<response xmlns="http://www.semantichacker.com/api">

<about>

<requestId>9044B06D269F5D28099F4D54E3FEDF5E</requestId>

<docId>93F725A07423FE1C889F448B33D21F46</docId>

<systemType>signature</systemType>

<configId>odp_2007_l1_1.7k</configId>

<contentType>text/plain</contentType>

<contentDigest>93F725A07423FE1C889F448B33D21F46</contentDigest>

<requestDate>2009-12-21T14:23:57+00:00</requestDate>

<systemVersion>2.0</systemVersion>

</about>

<siggen>

<siggenResponse>

<signature>

<dimension weight="0.59780616" index="399" label="Top/Computers/Programming/Languages/Development_Tools" />

<dimension weight="0.47518215" index="398" label="Top/Computers/Programming/Languages/Class_Libraries" />

<dimension weight="0.3850059" index="400" label="Top/Computers/Programming/Languages/Enterprise_Edition" />

<dimension weight="0.28773117" index="391" label="Top/Computers/Programming/Languages" />

<dimension weight="0.16868249" index="383" label="Top/Computers/Programming" />

<dimension weight="0.14804457" index="384" label="Top/Computers/Programming/Component_Frameworks" />

<dimension weight="0.136303" index="411" label="Top/Computers/Programming/Methodologies" />

<dimension weight="0.12356524" index="339" label="Top/Computers/Data_Formats/Markup_Languages/XML" />

<dimension weight="0.105650306" index="389" label="Top/Computers/Programming/Internet" />

<dimension weight="0.088537686" index="401" label="Top/Computers/Programming/Languages/JavaScript" />

<dimension weight="0.08403864" index="408" label="Top/Computers/Programming/Languages/Ruby" />

<dimension weight="0.075138405" index="407" label="Top/Computers/Programming/Languages/Python" />

</signature>

</siggenResponse>

</siggen>

</response>

Here about tag consists of response details and signature tag consists of dimension tag which has -

  • weight attribute which has weight of the dimension between 0 to 1.
  • index unique ID of the dimension.
  • and the meaningful representation on the dimension.

Step 9

Finally we will send the xml code to our client where jQuery will parse it and extract the information.


$sXML = get_data($url);

$oXML = new SimpleXMLElement($sXML, LIBXML_NOCDATA);

echo $oXML->siggen->siggenResponse->signature->asXML();

Here we will create a SimpleXMLElement object with response object as parameter. Then we will simply echo a part of the xml data.

Note: Here we could have parsed the data at the server side only, since we are dealing with more than one data pair, it was required to send the structured data at the client side.

Step 10

Finally our semantichacker.php look’s like -


<?php

$search = $_POST['search_text'];
$url ="http://api.semantichacker.com/ed4xlwf9/signature?content=$search&amp;amp;amp;amp;amp;amp;amp;amp;showLabels=true";

function get_data($path){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$path);
curl_setopt($ch, CURLOPT_FAILONERROR,1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$retValue = curl_exec($ch);
curl_close($ch);
return $retValue;
}

$sXML = get_data($url);
$oXML = new SimpleXMLElement($sXML, LIBXML_NOCDATA);
echo $oXML->siggen->siggenResponse->signature->asXML();

?>

Step 11

Now we are going to work with the Google Data book api which allows us to search books. Searching does not require any key or token. Now either we can work the same way as above for the google book api or Google provides a standalone high level library for working with its services which is distributed by the Zend. In this tutorial we will be using Zend GData api.

  • First download it from Zend.
  • Now we will extract it from the archive and copy the zend folder to our library folder.

Step 12

Now we are going to create a google_book.php in our library folder and start off with the following code.


require_once('Zend/Loader.php');

$search = $_POST['search_text'];

Here first we have included the zend’s loader file to work with the Google REST services and then we have taken the search string from POST array.

Step 13

Now we are going to load the required class that is the Google Book and instantiate an object.


Zend_Loader::loadClass('Zend_Gdata_Books');

$books = new Zend_Gdata_Books();

Step 14

Now since our object is created and we need to set some parameters for our search.


$query = $books->newVolumeQuery();

$query->setQuery($search);

$query->setMaxResults(10);

$query->setMinViewability('partial_view');

$feed = $books->getVolumeFeed($query);

Here

  • First we will create a need volume query needed for sending search request.
  • Then we will set our search string.
  • Now we will set maximum results we want.
  • And finally we will set preview status and execute the query.

The response we will get will be saved in the feed variable.

Step 15

Now finally using the foreach loop we will iterate through our feed and print the required data in a tabular format.


foreach ($feed as $entry) {

echo "<table >";

$link = $entry->getLink();

echo "<tr style='padding:10px;'><td style='width:100px;padding:4px'><img src='".$link[0]->getHref()."'></td>";

echo "<td>Title : ".$entry->getTitle();

echo "Volume ID: ".$entry->getVolumeId();

echo "<a href='".$link[1]->getHref()."'>click here</a></td></tr>";

}

echo "</table>";

Step 16

We will look at the details that we have outputted.

  • First we will output a img with src to the thumbnail image using $link[0]->getHref().
  • Then we will print the title of the book using getTitle().
  • Then we will print the Volume ID of the book using getVolumeId().
  • Finally we will output an anchor to the main link by using $link[1]->getHref().

Here we can use directly $entry->getHtmlLink() but due to some reason it doesnt work with for java and php libraries. So to get around it we will get a link array from the entry. It has a thumbail url at 0th position and main url at the 1st position.

Step 17

So finally our google_book.php code looks like -

<?php

require_once('Zend/Loader.php');
$search = $_POST['search_text'];

Zend_Loader::loadClass('Zend_Gdata_Books');
$books = new Zend_Gdata_Books();
$query = $books->newVolumeQuery();

$query->setQuery($search);

$query->setMaxResults(10);

$query->setMinViewability('partial_view');

$feed = $books->getVolumeFeed($query);

foreach ($feed as $entry) {

echo "<table>";

$link = $entry->getLink();

echo "<tr style='padding:10px'><td style='width:100px;padding:4px'><img>getHref()."'></td>";

echo "<td>Title : ".$entry->getTitle();

echo "Volume ID: ".$entry->getVolumeId();

echo "<a>getHref()."'>click here</a></td></tr>";

}

echo "</table>";

?>

Step 18

Now we will work on our html file that is index.html.


<html>

<head>

<script type="text/javascript" src="js/jquery.js"></script>

<script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"></script>

<script type="text/javascript" src="js/ui.core.js"></script>

<script type="text/javascript" src="js/ui.progressbar.js"></script>

<script type="text/javascript" src="js/main.js"></script>

<link rel="stylesheet" type="text/css" href="css/style.css" />

<link rel="stylesheet" type="text/css"  href="css/start/jquery-ui-1.7.2.custom.css" />

<title>Index</title>

</head>

<body>

<form>

<input type="text" id="search" class="ui-state-default" />

<a href="#" id="button" class=" ui-state-default ui-corner-all">Search</a>

</form>

<hr />

<div id="gbook">

<div class="ui-widget-header ui-corner-top" style="padding:4px; text-align:center">Book Search</div>

<div id="bookpane"></div>

</div>

<div id="sh"<

<div class="ui-widget-header ui-corner-top" style="padding:4px; text-align:center">Dimensions</div>

<ul id="progresspane">

<li><div class='progressbar'></div></li>

<li><div class='progressbar'></div></li>

<li><div class='progressbar'></div></li>

<li><div class='progressbar'></div></li>

<li><div class='progressbar'></div></li>

</ul>

</div>

</body>

</html>

Here we have -

  • Imported our required libraries like jQuery and jQuery UI for our progress bar widget and main.js in which we will work our javascript code.
  • We have also imported style.css for styling our page :) and jquery-ui-1.7.2.custom.css to access the UI framework.
  • There is also a form which consists of textbox and a search button( anchor).
  • We have two panels -
    1. First one will be to load our book data from Google Book API that is gbook div.
    2. Secondly we have a panel with five progress bars that will give indication according the weight.

Step 19

Now we will move to our style.css file and style up our page.


@charset "utf-8";

@import url('reset.css');

/* CSS Document */

body{

background:#000000;

color: #00CCFF;

font-family:Verdana, Arial, Helvetica, sans-serif;

font-size:23px;

}

a{

text-decoration:none;

}

#button{

padding:3px;

font-size:18px;

}

form{

padding:15px;

}

input[type=text]

{

padding:5px;

font-size:14px;

font-weight:bold;

}

#sh

{

display:none;

font-size:12px;

font-family: Verdana, Arial, Helvetica, sans-serif;

font-weight:bold;

width:500px;

}

#progresspane

{

border-color: #33CCFF;

border-style:solid;

border-width:1px;

padding-left:10px;

}

.label

{

display:block;

width:250px;

}

.progressbar

{

width:300px;

margin:5px;

}

#gbook

{

float:right;

width:450px;

margin-right:30px;

display:none;

}

#bookpane

{

border-color: #33CCFF;

border-style:solid;

border-width:1px;

padding-left:10px;

font-size:14px;

}

This is basic css code which is self explanatory.

Step 20

Now we are going to work with our javascript file that is main.js, so we will create a javascript file main.js in the js folder.

Step 21

We will start off by typing the following code -


$(document).ready(function(){

$('.progressbar').progressbar({ value: 0 });

});

Here we are intializing the progress bars with value 0.

Step 22

Now we will create an anonymous function in which we will add states for our textbox and button.


$(function()

{

$("#button").hover(

function(){

$(this).addClass("ui-state-active");

},

function(){$(this).removeClass("ui-state-active"); }

);

$("input[type=text]").focus(function(){  $(this).addClass("ui-state-focus");       });

$("input[type=text]").blur(function(){  $(this).removeClass("ui-state-focus");       });

})

Here we have added hover state for the button and states for textbox on focus and blur event.

Step 23

Now we will write code that will set up values for the progress bar.


$("#button").click(function(){

$("form").append("<img id='loader' src='img/loader.gif'>");

$("#sh").hide('normal');

$("#gbook").hide('normal');

var label;

var weight;

$("#progresspane li span").remove();

$.post("library/semantichacker.php",

{search_text:encodeURI($("#search").val()) } ,

function(data){

});

$("#sh").fadeIn('normal');

});

Here what we are doing is -

  • First when the button is clicked, we will add a loading icon.
  • Then we are going to hide both the panels if they visible, at first they will be hidden but when we will search again they need to be hidden again.
  • Now we are declaring weight and label variables which we will use later.
  • We will remove the span in the list item which we will add later.
  • Finally we will send the search query using the post method of jQuery.

Here we have wrapper the search query in the encodeURI function because if there are more than one word in the search, to send it to the REST we need to encode themt.

Step 24

Now on successful response, we will need to extract the values from our xml response and set the progress bars to their weights.


var count =0;

$(data).find("dimension").each(function() {

if(count<5)

{

var dim = $(this);

weight= dim.attr('weight') * 100;

label = dim.attr('label');

var id = $("#progresspane li:eq("+count+") div");

$("#progresspane li:eq("+count+")").prepend("<span class='label'>"+label+"</span>");

$(id).progressbar('option', 'value', weight);

count++;

}

Here we extract the weight and multiply it by 100, since our progress bar is in the range 0 to 100. Similarly we also extract the label. Then we will prepend the span in the list item with the label and set that progress bar value to the weight.

Here we are only interested in 5 dimension that’s why we have set the if condition.

Step 25

Now we will call the Google Book service using the post method of jQuery.


$.post("library/google_book.php",

{search_text:$("#search").val() } ,

function(data){

$("#bookpane").html(data);

$("#gbook").fadeIn('normal');

$("#loader").fadeOut('normal',function()

{   $(this).remove();    });

});

});

Here we pass on the search string and after a response we will load in the bookpane div and make in visible. Finally we will remove the loader.

Step 26

So our main.js code looks like -


$(document).ready(function(){
$('.progressbar').progressbar({ value: 0 });
});

$(function(){

$("#button").click(function(){
$("form").append("<img id='loader' src='img/loader.gif'>");
$("#sh").hide('normal');
$("#gbook").hide('normal');
var label;
var weight;
$("#progresspane li span").remove();

$.post("library/semantichacker.php",
{search_text:encodeURI($("#search").val()) } ,
function(data){
var count =0;
$(data).find("dimension").each(function() {

if(count<5)
{
var dim = $(this);
weight= dim.attr('weight') * 100;
label = dim.attr('label');
var id = $("#progresspane li:eq("+count+") div");
$("#progresspane li:eq("+count+")").prepend("<span class='label'>"+label+"<<span>");
$(id).progressbar('option', 'value', weight);

count++;
}

});

$("#sh").fadeIn('normal');

$.post("library/google_book.php",
{search_text:$("#search").val() } ,
function(data){
$("#bookpane").html(data);
$("#gbook").fadeIn('normal');
$("#loader").fadeOut('normal',function(){   $(this).remove();    });
});

});

});

$("#button").hover(
function(){
$(this).addClass("ui-state-active");
},
function(){$(this).removeClass("ui-state-active"); }
);

$("input[type=text]").focus(function(){  $(this).addClass("ui-state-focus");       });
$("input[type=text]").blur(function(){  $(this).removeClass("ui-state-focus");       });

})

Finally we are done and here’s what our mashup looks like. You can create your own mashup for your website with different features. Since all the services have the same basic principles we have used.

Want to see more examples goto Programmable Web.

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Add to favorites
  • Design Float
  • DZone
  • email
  • FriendFeed
  • PDF
  • Propeller
  • Reddit
  • RSS
  • StumbleUpon
  • Twitter

Related posts:

  1. Creating a 3D carousel from scratch
  2. Create URL Shortener For Twitter Using PHP
  3. How to Create a Simple API with PHP and MySQL
  4. Animate Text with jQuery Easing (screencast)
  5. Building a jQuery Step-by-Step Form


Written by brenelz

Hello everyone, I'm Brenley Dueck or better known as Brenelz. I currently run my own business called Brenelz Web Solutions which focuses primary on winnipeg website design. The web technologies I most specialize in are CSS, jQuery, AJAX, PHP, and the MySQL database. Please make sure to follow me on twitter.

 

One Response to “Create a Mashup from Scratch”

  1. AmdY Says:

    January 15th, 2010 at 2:12 pm

    why don’t use fz class Zend_Http for get data? it’s more flexible then curl and can easily change on sockets, …..

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
connect with me!