Archive

Posts Tagged ‘flickr’

Accessing the Flickr API from our CFWheels-powered site

June 17, 2011 Leave a comment

Recently at work, I was tasked with adding a one-off page to our site.  Normally, I hate these kinds of assignments. They tend to break any rules you already have established for the site architecture and style; and once you say “yes” to one such project, you open the floodgates for others.  However, I jumped at the opportunity since this was slightly new territory for me.  For this page I was asked if there was a way to display pictures from our Flickr page on a page in our site for an exhibition about snapshots.  Without thinking for too long, I answered yes.  I remember way back when I was exploring Ruby on Rails, one of the first demos I saw was the one where the speaker accessed the Flickr api to pull in images that matched a given tag he passed in.  I knew it was possible and fairly simple to do this.  What I didn’t know at the time was how to do it and stay within the conventions of the CFWheels framework.

The Requirement

Create a page for the exhibition that displays 4 or 5 thumbnail images from selected sets from our Flickr account.  Each image should be a link to the full image on the Flickr web site.  Under each group of images should be a link to the full set of images on the Flickr site. The page should list the set title and description, along with its thumbnails, followed by a link to the set on Flickr.  The selected photo set id’s would be provided.

My Solution

I decided that since the photoset id’s would be provided, I could make them a list.  I would then loop over the list and pass that it into the api to get the data I needed.  I could then loop over the resultsets to create the display.  Sounded simple enough.

Proof of Concept Prototype

After studying the Flickr public api, I settled on the flickr.photosets.getInfo() and flickr.photosets.getPhotos() methods to provide the data for the page.  First, I hit the flickr.photosets.getInfo() method to get the title and description of each photoset.  It looks something like this:

<cfset photosetList = “photosetID1, photosetID2, photosetID3, photosetID4”/>

<cfloop list = “#photosetList#” index=”x”>

<cfhttp url=”http://www.flickr.com/services/rest/” result=”photoSetResult”>

<cfhttpparam type=”url” name=”api_key” value=”myAPIKey”/>

<cfhttpparam type=”url” name=”method” value=”flickr.photosets.getInfo”/>

<cfhttpparam type=”url” name=”photoset_id” value=”#x#”/>

</cfhttp>

<!—Convert xml text response into an XML document—>

<cfset photosetXMLDoc = xmlParse(photosetResult.fileContent)/>

<cfset photosetNodes = xmlSearch(photosetXMLDoc, ‘//photoset’)/>

<!—Now grab the photos for this photoset—>

<cfhttp url=”http://www.flickr.com/services/rest/” result=”photosResult”>

<cfhttpparam type=”url” name=”api_key” value=”myAPIKey”/>

<cfhttpparam type=”url” name=”method” value=”flickr.photosets.getPhotos”/>

<cfhttpparam type=”url” name=”photoset_id” value=”#x#”/>

</cfhttp>

<cfset photosXMLDoc = xmlParse(photosResult.fileContent)/>

<cfset photosNodes = xmlSearch(photosXMLDoc, ‘//photo’)/>

<!—Loop over photosets to output photoset information—>

<cfloop from=”1” to=”#arrayLen(photosetNodes)#” index=”i”>

<cfset photosetsXML = xmlParse(photosetNodes[i]/>

<h2>#photosetsXML.photoset.title.xmlText</h2>

<p>#photosetsXML.photoset.description.xmlText</p>

<!—display 5 thumbnail images from each photoset—>

<cfloop from=”1” to=”5” index=”y”>

<cfset photosXML = xmlParse(photosNodes[y])/>

<div class=”flickrThumbs”>

<a href=”http://www.flickr.com/photos/user_id/#photosXML.photo.xmlAttributes.id#/” target=”_blank”><img src=”http://farm#PhotosXML.photo.XMLAttributes.farm#.static.flickr.com/#PhotosXML.photo.XMLAttributes.server#/#PhotosXML.photo.XMLAttributes.id#_#PhotosXML.photo.XMLAttributes.secret#_m.jpg” alt=#PhotosXML.photo.XMLAttributes.title#”/></a>

</div>

</cfloop>

<br class=”clear”/>

<a href=”” target=”_blank”>View all snapshots in this set</a>

</cfloop>

</cfloop>

The above code works just fine and honestly, my internal client is satisfied with it.  But I have a couple of problems with it.

    1. All this code is in the view file.
    2. If they decide they like this and want another similar page, I have to code an entirely new page with similar calls to the api.
    3. Logic and display all mixed together.
    4. It’s a lot of code ~50 lines.

A Better Way

There had to be a better way to separate logic and display and a way to make the api calls available to any view that needs it in the future.  I knew there were CF scripts available for the Flickr api, but they aren’t ready made for CFWheels.  I figured there would be a Flickr plugin and I was right.  I downloaded the SimpleFlickr plugin and got to reading the documentation.

I was able to determine the plugin would do most of what I needed so I set about tweaking it a bit to get the rest.  Turns out it was fairly simple and enabled me to separate out the logic from the display and make the api available across the site.  Craig Kaminsky created the plugin which provided a great starting point for me.  I contacted Craig to let him know I was using the plugin and wanted to tweak it a bit and he offered to integrate my changes into the full plugin.  The SimpleFlickr plugin is installed in the plugins folder in my site and I modified the SimpleFlickr.cfc a bit to get the additional information needed for my display.  So now my display code looks something like this.

<cfloop list=”#photosetList#” index=”x”>

<cfloop from=”1″ to=”#arrayLen(photosets)#” index=”i”>

<cfif x EQ “#photosets[i].id#”>

<h2>#photosets[i].title# (#photosets[i].id#)</h2>

<p>#photosets[i].description#</p>

<cfset photos = getFlickrPhotoSetPhotos(#photosets[i].id#)/>

<cfloop from=”1″ to=”6″ index=”y”>

<div>

<a href=”#photos[y].link#” target=”_blank”><img src=”#photos[y].url#” alt=”#photos[y].title#”/></a>

</div>

</cfloop>

<br class=”clear”/>

</cfif>

</cfloop>

<a href=”http://www.flickr.com/photos/#application.flickr_user_id#/sets/#Trim(x)#/&#8221; target=”_blank”><strong>View All Snapshots in this Theme</strong></a>

</cfloop>

Ahh, that’s much better.  Less code. No logic in the display.  And any page in the future can call the api.  Of course the result is identical to the client.  I can live with that.

Nearly all of my modifications to the plugin were to the private methods that deal with manipulating the resultset from Flickr.  Chiefly, I worked on the $getPhotosFromJSON() method to build the link url that would be used in my display.  This also required me to add the photoset.owner and photoset.id into my return array.  I have to thank Craig again for building the plugin in the first place which allowed me to tweak it to my needs.  I really think this plugin is useful for those who need some basic functions from Flickr in their CFWheels apps.

Advertisements