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 !!
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 -
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.
We will start off by creating our directory structure.
Here -
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 .
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 -
First of all to work with web services in PHP, we will need to enable the curl extension. To do this we will -
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.
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.
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.
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 -
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.
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;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();
?>
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.
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.
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();
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
The response we will get will be saved in the feed variable.
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>";
We will look at the details that we have outputted.
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.
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>";
?>
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 -
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.
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.
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.
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.
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 -
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.
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.
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.
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.
why don’t use fz class Zend_Http for get data? it’s more flexible then curl and can easily change on sockets, …..
Twitter
Follow me on Twitter to keep up to date!
RSS Feed
Keep up with all of our updates by subscribing to our RSS feed!
FaceBook
Join our group on Facebook and become a fan of us!