Tuesday, November 29, 2005

CFMX and Amazon web services, pt 4

In this part, we're going to build simple form and action pages that will incorporate the lessons learned previously.

The form itself is built using Cold Fusion MX 7. It consists of a select field, input field and a submit button.

Amazon.cfm

<cfoutput>

<cfform name="getItem" action="displayresults.cfm" method="post">
<cfselect label="Department:" name="SearchIndex" required="true">
<option value="">...select a department...</option>
<option value="DVD">DVD</option>
<option value="Software">Software</option>
<option value="Books">Books</option>
<option value="PCHardware">PCHardware</option>
<option value="Music">Music</option>
<option value="VideoGames">VideoGames</option>
</cfselect>
<br/>
<cfinput type="text" name="keyword" label="Enter Keyword:" required="false" />
<cfinput type="submit" name="Submit">
</cfform>
</cfoutput>

Now, comes the meaty part.

Displayresults.cfm

<!--- creates record paging parameter if it doesn't exist --->
<cfif not isdefined("url.f")>
<cfset url.f = 1>
</cfif>

<!--- checks to see if url.s exists, if yes then page was reloaded via the record paging and creates SearchIndex variable and assigns url.s value to it.
otherwise, the code checks to see if form.SearchIndex exists and then creates SearchIndex variable with form.SearchIndex value.
--->
<cfif isDefined("url.s")>
<cfset SearchIndex = URLDecode(url.s)>
<cfelseif isDefined("form.SearchIndex")>
<cfset SearchIndex = form.SearchIndex>
</cfif>

<!--- checks to see if url.k is defined. if yes, then page has been reloaded via record paging and creates Keyword variable and assigns url.k to it.
otherwise, code checks to see if form.keyword exists. if yes, then user was directed here by form page. Keyword var is created and assigned value of form.keyword.
--->
<cfif isDefined("url.k")>
<cfset Keyword = url.k>
<cfelseif isDefined("form.keyword")>
<cfset Keyword = form.keyword>
</cfif>

<!--- creates amz var, which contains all the variables needed to create a viable search entry.
note that, for our purposes here, only the SearchIndex, Keywords and ItemPage variables have dynamic values.
--->
<cfset amz = "">
<cfset amz = amz & "&Operation=ItemSearch">
<cfset amz = amz & "&SearchIndex=" & SearchIndex>
<cfset amz = amz & "&Keywords=" & keyword>
<cfset amz = amz & "&ResponseGroup=Medium,Images">
<cfset amz = amz & "&ItemPage=#url.f#">

<!--- service call to Amazon web services. Please replace the 'xxxx' with your Subscription ID.
The results, if the call is successful, is stored in a variable called xmlObj.
--->
<cfhttp url="http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&SubscriptionId=xxxxx&#amz#" result="xmlObj">

<!--- use XMLParse function to create tmp variable --->
<cfset tmp = XMLParse(XMLObj.filecontent)>

<!--- use ArrayLen to find out how many products are in XML packet and assign value to numAmzItem variable
--->
<cfset numAmzItem = ArrayLen(tmp.itemsearchresponse.items.xmlchildren)-3>

<!--- was search request valid/execute properly. assigns True or False value--->
<cfset chkRequest = tmp.ItemSearchResponse.Items[1].Request.IsValid.xmltext>

<!--- if chkRequest is True, begin sifting through xml packet --->
<cfif chkRequest>

<!---
create new array to carry product data --->
<cfset lstItem = ArrayNew(1)>

<!--- begin looping through xml packet --->
<cfloop from="1" to="#numAmzItem#" index="i">

<!--- convert current lstItem iteration into structure --->
<cfset lstItem[i] = StructNew()>

<!--- checks for ASIN
if one is found, then lstItem[i] structure is filled out with following info
--->
<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i],"ASIN")>
<cfset lstItem[i].ASIN = tmp.ItemSearchResponse.Items[1].Item[i].ASIN.xmltext>

<!--- check to see if Author exists --->

<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes,"Author")>
<cfset lstItem[i].Author = tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes.Author.xmltext>
</cfif>
<!--- insert amazon.com URL for item --->
<cfset lstItem[i].URL = tmp.ItemSearchResponse.Items[1].Item[i].DetailPageURL.xmltext>
<!--- Name of product --->
<cfset lstItem[i].Title = tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes.Title.xmltext>
<!--- small image url and sizes--->
<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i],"SmallImage")>
<cfset lstItem[i].smImage = tmp.ItemSearchResponse.Items[1].Item[i].SmallImage.URL.xmlText>
<cfset lstItem[i].smImageH = tmp.ItemSearchResponse.Items[1].Item[i].SmallImage.Height.xmlText>
<cfset lstItem[i].smImageW = tmp.ItemSearchResponse.Items[1].Item[i].SmallImage.Width.xmlText>
</cfif>

<!--- checks for list price (if available) or lowest used price
sets price to $0.00 if no pricing info found
--->
<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes,"ListPrice")>
<cfset lstItem[i].Price = tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes.ListPrice.FormattedPrice.xmlText>
<cfset lstItem[i].Amount = tmp.ItemSearchResponse.Items[1].Item[i].ItemAttributes.ListPrice.Amount.xmlText>
<cfelseif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i].OfferSummary,"LowestUsedPrice")>
<cfset lstItem[i].Price = tmp.ItemSearchResponse.Items[1].Item[i].OfferSummary.LowestUsedPrice.FormattedPrice.xmlText>
<cfset lstItem[i].Amount = tmp.ItemSearchResponse.Items[1].Item[i].OfferSummary.LowestUsedPrice.Amount.xmlText>
<cfelse>
<cfset lstItem[i].Price = DollarFormat(0)>
<cfset lstItem[i].Amount = 0>
</cfif>
<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i],"ProductGroup")>
<cfset lstItem[i].ProductGroup = tmp.ItemSearchResponse.Items[1].Item[i].ProductGroup.xmlText>
</cfif>
<!--- check for Editorial Review content --->
<cfif structkeyexists(tmp.ItemSearchResponse.Items[1].Item[i],"EditorialReviews")>
<cfset lstItem[i].Review = Left(tmp.ItemSearchResponse.Items[1].Item[i].EditorialReviews.EditorialReview.Content.xmlText,100)>
</cfif>
</cfif>
</cfloop>
</cfif>

<style type="text/css">
body {font-family:tahoma;background-color:##fff}
th {font-size:14px;font-weight:bold;text-align:center;color:##ff0000}
td {font-size:12px;color:##000;padding:10px 5px 10px 0;}
</style>
<html>
<head></head>
<body>
<!--- begin outputting results--->
<cfoutput>
<!--- is chkRequest True?--->
<cfif chkRequest>
<!--- Yes! --->

<!--- begin loop to create record paging --->
<cfloop from="1" to="#tmp.ItemSearchResponse.Items.TotalPages.xmltext#" index="f">
<a href="displayresults.cfm?f=#f#&s=#URLEncodedFormat(SearchIndex)#&k=#URLEncodedFormat(keyword)#">#f# </a>
</cfloop>
<!--- end loop --->

<!--- create table --->
<table border="0" cellpadding="0" cellspacing="0" width="650" align="center">

<!---
begin display result loop--->
<cfloop from="1" to="#numAmzItem#" index="i">

<!---
check to see if there is at least 1 copy of product available --->
<cfif lstItem[i].Amount gt 0>

<!---
set row background colors --->
<tr bgcolor="###iif(i MOD 2,DE('dfdfdf'),DE('f4f4f4'))#">
<!--- display image in first cell and link it to Amazon product page --->
<td><cfif structkeyexists(lstItem[i],"smImage")>
<a href="#lstItem[i].URL#"><img src="#lstItem[i].smImage#" width="#lstItem[i].smImageW#" height="#lstItem[i].smImageH#" border="0" /></a>
<cfelse>
<!--- if there is no image, then a default image is shown. You can use your own imagery instead --->
<img src="noimage.png">
</cfif></td>

<!--- second cell contains item name and ASIN and links product name to Amazon product page --->
<td><a href="#lstItem[i].URL#">#lstItem[i].Title#</a> [#lstItem[i].ASIN#]<br />
<!--- display editorial content, if any --->
<cfif structkeyexists(lstItem[i],"Review")>#lstItem[i].Review# <a href="#lstItem[i].URL#">(more)</a></cfif>
</td>
<!--- display product price --->
<td>#lstItem[i].Price#</td>
</tr>
</cfif>
</cfloop>
<tr>
<td>

<!--- create new row containing button to return back to form page--->
<cfform name="return" action="amazon.cfm" method="post">
<cfinput type="submit" name="Submit">
</cfform>
</td>
</tr>
</table>
<cfelse>
<!--- if no results found or there is an error, display no results message --->
No results found. Please try again
</cfif>
</cfoutput>

</body>
</html>

The above files will give you a quick view of how to extract data from the Amazon web services. This is not the end of the road, however. There are numerous ways of building sites, ranging from individual product links scattered across a site to product pages to search pages.

In the future, I will be posting additional articles on how to use CFMX to build a bigger, better Amazon-based store. Enjoy your new toy.

Be cool,

Chris

No comments: