Integrating Flickr Photostreams with PHP using the Zend Framework
Integrating Flickr Photostreams with PHP
Lights! Camera! Upload!
Like most people with a digital camera, I tend to be a heavy Flickr user. Not only does Flickr make it easy to share my ever-growing photo collection with colleagues and family, but its drag-and-drop photo organizer and geo-tagging features make it easy to quickly categorize and find pictures from, say, my 2003 holiday in Goa.
The really good stuff, though, is hidden behind the scenes. Like many Web 2.0 applications, Flickr exposes its data to the public via a REST API, making it possible to develop customized applications that run on top of the base service. This REST API allows access to a number of important functions, including photo searching, tagging and uploading; photoset retrieval; contact retrieval; and panda recommendations. It’s also pretty easy to integrate this REST API into a PHP application – and this article will show you how!
Getting Started
Before diving into the code, a few notes and assumptions. I’ll assume throughout this article that you’re familiar with HTML, SQL and XML, and that you have a working Apache/PHP/MySQL development environment. I’ll also assume that you know the basics of working with classes and objects in PHP, as all the components used in this article are written in compliance with OOP principles.
In order to get started using PHP, REST and the Flickr API, there are a couple of things you’ll need:
- First, you need the Zend Framework’s Zend_Rest_Client component, which you can download from the Zend Framework Web site. Installing the framework is typically as simple as uncompressing the distribution archive and adding the location of the resulting
Zend/directory to the PHP include path. - Second, you need a Flickr API key. Drop by the Flickr Web site, register an account with Flickr, and then pick up your free API key and shared secret. These credentials will be needed to gain access to the Flickr REST API, so hang on to them tight.
- Third, you need to keep a copy of the Flickr API documentation easily accessible. This documentation is your roadmap to working with the Flickr API – it contains detailed information on available API calls, input parameters, error codes and return values, together with information on how to integrate and use the Flickr API with different programming languages. You’ll be referring to it frequently throughout this tutorial.
All set up? Let’s rock and roll.
Feeling Restless
Flickr’s API can be accessed using the standard HTTP GET method, with the method name and arguments encoded into the request URL and the method response returned as an XML document. Here’s an example of one such API request:
GET http://api.flickr.com/services/rest/? method=flickr.tags.getHotList& api_key=API_KEY_HERE& period=week
Typically, every API request will include at least two parameters, the method name ('method') and the API key ('api_key'). Some API methods require additional arguments, which are appended to the request as additional GET parameters. For every request, the Flickr API will return an XML-encoded response, which includes a status field indicating whether the request was successful ('ok') or not ('fail').
Here’s an example of the response packet returned by a successful API request:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="ok"> <hottags period="week" count="20"> <tag score="100">nieuwjaarsduik</tag> <tag score="100">tgamprorogue</tag> <tag score="100">australiaday2010</tag> <tag score="100">jan25</tag> <tag score="100">jan22</tag> <tag score="100">nieuwjaarsdag</tag> <tag score="100">noprorogue</tag> <tag score="100">jan26</tag> <tag score="100">blacknazarene</tag> <tag score="100">dec28</tag> <tag score="100">sftu</tag> <tag score="100">jan232010</tag> <tag score="100">wcbos</tag> <tag score="100">canadiansagainstproroguingparliament</tag> <tag score="100">jan172010</tag> <tag score="100">dec27</tag> <tag score="100">jan222010</tag> <tag score="100">californiathunderstorms</tag> <tag score="100">s44</tag> <tag score="100">librarydayinthelife</tag> </hottags> </rsp>
And here’s an example of the response returned when the API call was unsuccessful:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="fail"> <err code="100" msg="Invalid API Key (Key has invalid format)" /> </rsp>
Since the response packet is delivered in XML, any XML-aware programming language can be used to read and process the response. With PHP, for example, you could use PHP’s SimpleXML or DOM extension to parse the response packet and extract relevant information from it. There are also a number of third-party libraries that are specifically designed to parse Flickr API responses and convert them to native PHP objects for easier processing; you’ll see some of these at the end of this article.
It’s worth noting that, in addition to an API key, some parts of the Flickr API also require the user to be authenticated with a separate authentication token. The token generation process is somewhat complicated, as Flickr doesn’t (yet) support OAuth authentication, and is discussed in detail in the Flickr API documentation. However, you don’t need to worry about this just yet, because all the examples in this article are based on methods that can be accessed with just an API key.
The Hot List
Now that you know the basics of the Flickr API, let’s look at it in the context of a PHP application. Consider the following script, which uses Zend_Rest_Client to parse the XML returned by the flickr.tags.getHotList method (as shown in the previous page) and display a list of top tags on Flickr from the last 24 hours:
<?php
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.tags.getHotlist');
$client->api_key(API_KEY);
// set method arguments
$client->period('day');
// perform request and process respone
try {
$result = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head></head>
<body>
<h2>Hot tags on Flickr in the last 24 hours:</h2>
<ul>
<?php foreach ($result->hottags->tag as $tag):?>
<li><?php echo $tag; ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>
This script begins by setting up the Zend auto-loader, which takes care of automatically loading Zend Framework components as needed. It then initializes an instance of Zend_Rest_Client and passes the object constructor the base URL to the Flickr REST API. This Zend_Rest_Client object is a generic HTTP client that can be used to perform GET, POST, PUT and DELETE requests in a REST context.
Request parameters are specified as object methods, with the parameter value specified as an input argument to the corresponding method. So, for example, a call to $client->period('day') would be converted into the request argument period=day. This object-oriented approach provides a convenient way to add multiple arguments to a REST request.
Once the request arguments are specified, the request is transmitted to the server using the appropriate HTTP method. The Zend_Rest_Client object exposes magic methods corresponding to the four HTTP methods. Therefore, calling $client->get() transmits a GET request, while calling $client->post() generates a POST request. The response returned by the server is automatically converted into a Zend_Rest_Client_Result object; individual elements of the response can now be accessed as properties of this object. This is illustrated in the previous example, which uses $object->property notation to navigate through the XML document and iterate over the tag collection returned by the server.
Here’s an example of what the output looks like:

Searching For Answers
One of the most common things users do on Flickr.com, is search for photos matching one or more tags. The Flickr REST API makes it possible to integrate this functionality into a PHP application via the flickr.photos.search method, which accepts a variety of input parameters and returns an XML-encoded result of photos matching these parameters.
To see this in action, consider the next example:
<?php
if (isset($_POST['submit'])) {
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.photos.search');
$client->api_key(API_KEY);
// set method arguments
$client->tags($_POST['q']);
$client->per_page(25);
// perform request and process response
try {
$result = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Tags:
<input type="text" name="q" />
<input type="submit" name="submit" value="Search" />
</form>
<?php if (isset($result)): ?>
<h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
<ul>
<?php foreach ($result->photos->photo as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</body>
</html>
This script sets up an HTML form with a single text input field for the user to enter one or more tags. When the form is submitted, the script initializes a new Zend_Rest_Client object and invokes the flickr.photos.search method, passing it the set of tags to search for.
Here’s an example of what the response might look like:
<?xml version="1.0" encoding="utf-8" ?> <rsp stat="ok"> <photos page="1" pages="7944" perpage="10" total="79439"> <photo id="43138737" owner="43xx1019@Nxx" secret="secret" server="4618" farm="5" title="St Stephens Tower." ispublic="1" isfriend="0" isfamily="0" /> <photo id="43194545" owner="10xxx882@Nxx" secret="secret" server="4751" farm="5" title="Big Ben" ispublic="1" isfriend="0" isfamily="0" /> <photo id="13802222" owner="3xx22xx54@Nxx" secret="secret" server="4766" farm="5" title="Where are you ?" ispublic="1" isfriend="0" isfamily="0" /> <photo id="42959565" owner="56658xx5@Nxx" secret="secret" server="4374" farm="5" title="Big Ben" ispublic="1" isfriend="0" isfamily="0" /> <photo id="43680418" owner="2153x46@Nxx" secret="secret" server="4922" farm="5" title="Big Ben" ispublic="1" isfriend="0" isfamily="0" /> </photos> </rsp>
As this output illustrates, the output of the flickr.photos.search method is an XML-encoded list of <photo> elements, each containing details of the corresponding photo file. These details include the unique photo identifier, the server and farm identifier, and the owner identifier. It’s now easy to iterate over this result object, displaying the data as a Web page.
A word here about how the photo and page URLs are generated. Take a look at the XML output of the flickr.photos.search method, and you’ll that it doesn’t directly include the photo URL or photo page URL. Instead, all it contains is a set of numeric identifiers for the photo, server, farm, and owner. These identifiers need to be manually arranged into a URL, as described in the Flickr API URL guidelines. This has been done in the previous example, and you’ll see it in subsequent examples as well.
Here’s an example of what the output might look like:

In case you’re wondering, the flickr.photos.search method accepts a wide range of search criteria, including photo location (latitude and longitude), upload date, capture date, license, keywords, owner, group, privacy, and many others. For a complete explanation of the various options, take a look at the corresponding manual page.
Going Public
It’s also possible to retrieve a particular’s user public photos, given the user’s Flickr ID. This is accomplished with the flickr.people.getPublicPhotos method, which accepts a 'user_id' argument and returns a list of public photos uploaded by the corresponding user. Here’s an example:
<?php
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.people.getPublicPhotos');
$client->api_key(API_KEY);
// set method arguments
$client->user_id('47xxxx00@Nyy');
// perform request and process response
try {
$result = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Public photos:</h2>
<ul>
<?php foreach ($result->photos->photo as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
In this example, a unique user identifier is passed to the flickr.people.getPublicPhotos, via the ‘user_id’ argument. The return value of the method is an XML document similar to that shown on the previous page: a set of <photo> elements, each representing a public photo from the specified user’s collection. As before, it’s quite easy to iterate over this element collection, generating links to each photo and photo page.
Here’s an example of what the output might look like:

Game, Set, Match
Flickr allows users to organize photos into collections (“sets”), similar to a traditional photo album. Each set has a unique name, and can be accessed via a unique URL that displays thumbnails of all the photos in the set. From an API perspective, these functions can be implemented via the flickr.photosets.getList and flickr.photosets.getPhotos method. The former accepts a user identifier and returns a list of that user’s photo sets; the second accepts a set identifier and returns a list of the photos in that set.
These two methods make it possible to retrieve and display the photo sets created by a user. Consider the following example, which illustrates:
<?php
if (isset($_POST['submit'])) {
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.photosets.getList');
$client->api_key(API_KEY);
// set method arguments
$client->user_id($_POST['uid']);
// perform request and process respone
try {
$list = $client->get();
unset($client);
$results = array();
foreach ($list->photosets->photoset as $photoset) {
$id = (string)$photoset['id'];
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
$client->method('flickr.photosets.getPhotos');
$client->api_key(API_KEY);
$client->photoset_id($id);
$results[$id] = array();
$results[$id]['title'] = (string)$photoset->title;
$results[$id]['data'] = $client->get();
unset($client);
}
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
p.set {
clear: both;
}
</style>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Flickr user ID:
<input type="text" name="uid" />
<input type="submit" name="submit" value="Search" />
</form>
<?php if (isset($results)): ?>
<h2>Search Results</h2>
<?php foreach ($results as $id => $arr): ?>
<p class="set">
<h3><?php echo $arr['title']; ?> (<?php echo $arr['data']->photoset['total']; ?> photos)</h3>
<ul>
<?php foreach ($arr['data']->photoset->photo as $photo): ?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</p>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
This script generates a Web form that asks for a Flickr user identifier. It then uses this identifier with the flickr.photosets.getList API method to return a list of sets created by that user. Each set has a unique set identifier; this is used to obtain a list of photos in each set via the flickr.photosets.getPhotos API method. The output of these two methods is combined to create a composite result array, which is then processed to produce a complete list of the user’s sets, with thumbnails of the images in each set.
Here’s an example of what the output looks like:

It’s important to note that when using these methods without authentication, only those sets containing public photos will be returned. Sets that contain only private photos, or a mix of public and private photos, will not be included in the return value.
Making New Friends
In all the previous examples, one of the key inputs to the Flickr API was the user’s Flickr identifier. But what if you don’t have this information available? Relax, because the Flickr API includes two methods, flickr.people.findByEmail and flickr.people.findByUsername, which can be used to directly obtain a Flickr user identifier from a user’s email address or user name.
Here’s a simple example that illustrates, requesting the user’s email address or user name and returning the corresponding Flickr identifier:
<?php
if (isset($_POST['submit'])) {
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->api_key(API_KEY);
if (!empty($_POST['email'])) {
$client->method('flickr.people.findByEmail');
$client->find_email($_POST['email']);
} else if (!empty($_POST['username'])) {
$client->method('flickr.people.findByUsername');
$client->username($_POST['username']);
}
// perform request and process response
try {
$results = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
p.set {
clear: both;
}
</style>
</head>
<body>
<h2>Search Users</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Flickr email address:
<input type="text" name="email" />
Flickr user name:
<input type="text" name="username" />
<input type="submit" name="submit" value="Search" />
</form>
<?php if (isset($results)): ?>
<h2>Search Results</h2>
Flickr user ID: <?php echo ($results->user['nsid']) ? $results->user['nsid'] : 'Not found'; ?>
<?php endif; ?>
</body>
</html>
Here’s a sample of the output:

The user identifier can be used to obtain the user’s complete Flickr profile, which includes such information as the user’s full name, location, photo URL and photo count. This information is provided by the flickr.people.getInfo, which accepts a Flickr user identifier and returns all available profile information.
Here’s a revision of the previous example, that uses the information returned by the flickr.people.findByEmail and flickr.people.findByUsername and generates a new API request for flickr.people.getInfo to display the user’s complete profile:
<?php
if (isset($_POST['submit'])) {
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->api_key(API_KEY);
if (!empty($_POST['email'])) {
$client->method('flickr.people.findByEmail');
$client->find_email($_POST['email']);
} else if (!empty($_POST['username'])) {
$client->method('flickr.people.findByUsername');
$client->username($_POST['username']);
}
// perform request and process response
try {
$results = $client->get();
$nsid = (string)$results->user['nsid'];
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
$client->api_key(API_KEY);
$client->method('flickr.people.getInfo');
$client->user_id($nsid);
$info = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
p.set {
clear: both;
}
</style>
</head>
<body>
<h2>Search Users</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Flickr email address:
<input type="text" name="email" />
Flickr user name:
<input type="text" name="username" />
<input type="submit" name="submit" value="Search" />
</form>
<?php if (isset($info)): ?>
<h2>Search Results</h2>
Flickr user ID: <?php echo $info->person['id']; ?> <br/>
Flickr user name: <?php echo $info->person->username; ?> <br/>
Real name: <?php echo $info->person->realname; ?> <br/>
Location: <?php echo $info->person->location; ?> <br/>
Photo count: <?php echo $info->person->photos->count; ?> <br/>
Photo URL: <a href="<?php echo $info->person->photosurl; ?>"><?php echo $info->person->photosurl; ?></a> <br/>
<?php endif; ?>
</body>
</html>
Here’s an example of the output:

Panda Power
It’s also possible to use the Flickr API to retrieve a list of interesting photos (according to user feedback) for the day or week. The Flickr API method to do this is called flickr.interestingness.getList and it returns an XML-encoded list of interesting photos, which can then be parsed and displayed as usual. Here’s an example:
<?php
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.interestingness.getList');
$client->api_key(API_KEY);
// set method arguments
$client->per_page(25);
// perform request and process response
try {
$result = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Interesting photos on Flickr today</h2>
<ul>
<?php foreach ($result->photos->photo as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
And here’s a sample of the output:

An alternative way to access interesting Flickr photos is by querying the Flickr Pandas, each of which returns a different set of photos depending on their mood. There are currently three pandas to choose from – Ling Ling, Hsing Hsing and Wang Wang – and you can access them with the flickr.panda.getPhotos method.
Here’s an example of using the photo stream provided by Ling Ling:
<?php
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.panda.getPhotos');
$client->api_key(API_KEY);
// set method arguments
$client->panda_name('ling ling');
$client->per_page(25);
// perform request and process response
try {
$result = $client->get();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>ling Ling's photos</h2>
<ul>
<?php foreach ($result->photos->photo as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
And here’s a sample of the output:

You can read more about the Flickr Pandas here.
Photo Pool
The Flickr API also provides access to Flickr groups, which are essentially collections of users sharing the same set of interests. Each group has a common “photo pool”, and the API makes it easy to both search for groups matching specified keywords, and retrieve photos from each matching group’s photo pool.
Here’s an example of how to do this:
<?php
if (isset($_POST['submit'])) {
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize client with data set
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
// set method name and API key
$client->method('flickr.groups.search');
$client->api_key(API_KEY);
// set method arguments
$client->text($_POST['q']);
$client->per_page(5);
$client->page(1);
// perform request and process response
try {
$list = $client->get();
$data = array();
foreach ($list->groups->group as $l) {
unset($client);
$nsid = (string)$l['nsid'];
$client = new Zend_Rest_Client('http://api.flickr.com/services/rest/');
$client->method('flickr.groups.pools.getPhotos');
$client->api_key(API_KEY);
$client->group_id($nsid);
$client->per_page(5);
$client->page(1);
$result = $client->get();
if (is_object($result->photos)) {
$data[$nsid]['name'] = (string)$l['name'];
$data[$nsid]['photos'] = $result->photos;
}
}
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
}
li img {
border: solid 2px black;
padding: 4px;
}
p.set {
clear: both
}
</style>
</head>
<body>
<h2>Search</h2>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
Search groups for:
<input type="text" name="q" />
<input type="submit" name="submit" value="Search" />
</form>
<?php if (isset($result)): ?>
<h2>Search results for '<?php echo $_POST['q']; ?>'</h2>
<?php foreach ($data as $g):?>
<p class="set">
<h3><?php echo $g['name']; ?></h3>
<ul>
<?php foreach ($g['photos']->photo as $photo): ?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</p>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
In this example, the keywords entered by the user are first sent to the flickr.groups.search API method, which returns a list of matching groups. Then, the flickr.groups.pools.getPhotos is used to obtain a set of photos from each group. This information is then parsed and displayed as an HTML page. Here’s an example of the output:

Different Strokes
Thus far, all the examples you’ve seen have used the Zend_Rest_Client object, which provides a generic client implementation for REST requests. However, just like there are multiple ways to skin a cat, so too are there multiple alternatives to this generic implementation:
- phpFlickr is a PHP 4.x/PHP 5.x implementation by Dan Coulter that provides access to every Flickr API method. It returns PHP array representations of Flickr API responses, and includes a callback script for Flickr user authentication.
- Phlickr is a PHP 5.x implementation by Andrew Morton that provides a wrapper around the Flickr API, returning a SimpleXM representation of API responses. It includes support for Flickr API user authentication, and assumes that your PHP installation includes support for both SimpleXML and cURL.
- Zend_Service_Flickr is a Flickr-specific REST client implementation that is part of the Zend Framework. The implementation includes pre-defined methods for searching photos by tag and group, and for retrieving user information.
It’s instructive to compare these different implementations and understand the approach taken by each one. Here’s an example of using phpFlickr (v2.3.1) to search for photos matching the tag ‘ibiza’:
<?php
// include class
include_once 'phpFlickr/phpFlickr.php';
// define API key and secret
define (API_KEY, 'XXXYYYZZZ');
define (SECRET, 'AAABBBCCC');
// initialize service object
$service = new phpFlickr(API_KEY);
try {
// execute a REST API method
$result = $service->photos_search(array('tags' => 'ibiza', 'per_page' => 25));
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Search results</h2>
<ul>
<?php foreach ($result['photo'] as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
The phpFlickr class provides “proxy methods” for the Flickr API, mapping the remote flickr.photos.search API method through the local photos_search() class method. The response is then represented as a set of nested arrays that can be easily processed with a foreach() loop.
Here’s an example of the output:

Another option is the Phlickr class, which provides a complete object implementation of the Flickr API. Here’s an example of using Phlickr (v.0.2.8) to access the same flickr.photos.search API method:
<?php
// include class
include_once 'Phlickr/Api.php';
// define API key and secret
define (API_KEY, 'XXXYYYZZZ');
define (SECRET, 'AAABBBCCC');
// instantiate service object with API key and secret
$api = new Phlickr_Api(API_KEY, SECRET);
try {
// execute a REST API method
$response = $api->executeMethod(
'flickr.photos.search',
array('tags' => 'ibiza', 'per_page' => 25)
);
// retrieve response as SimpleXML object
$xml = $response->getXml();
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Search results</h2>
<ul>
<?php foreach ($xml->photos->photo as $photo):?>
<?php $photoUrl = sprintf('http://farm%s.static.flickr.com/%s/%s_%s_t.jpg', $photo['farm'], $photo['server'], $photo['id'], $photo['secret']); ?>
<?php $pageUrl = sprintf('http://www.flickr.com/photos/%s/%s', $photo['owner'], $photo['id']); ; ?>
<li>
<img src="<?php echo $photoUrl; ?>"/>
<br/>
<?php echo $photo['title']; ?>
<br/>
<a href="<?php echo $pageUrl; ?>">Flickr photo page</a>
<?php echo $tag; ?>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
Similar to the approach followed by Zend_Rest_Client, this implementation too returns a response object. The object’s getXml() method can be used to retrieve a SimpleXML object representation of the response.
The Zend Framework also includes a Flickr-specific client via the Zend_Service_Flickr component. This component exposes a set of pre-defined methods, including the tagSearch() for tag-based photo search. Here’s an example of how to use it:
<?php
// include auto-loader class
require_once 'Zend/Loader/Autoloader.php';
// define API key and secret
define (API_KEY, 'XXXYYYZZZ');
// register auto-loader
$loader = Zend_Loader_Autoloader::getInstance();
// initialize service object
$service = new Zend_Service_Flickr(API_KEY);
try {
// execute a REST API method
$results = $service->tagSearch('ibiza', array('per_page' => 25));
} catch (Exception $e) {
die('ERROR: ' . $e->getMessage());
}
?>
<html>
<head>
<style type="text/css">
ul {
display: inline;
}
li {
float: left;
list-style-type: none;
padding: 10px;
font-size: smaller;
text-align: center;
height: 150px;
width: 150px;
}
li img {
border: solid 2px black;
padding: 4px;
}
</style>
</head>
<body>
<h2>Search results</h2>
<ul>
<?php foreach ($results as $result): ?>
<li>
<img src="<?php echo $result->Thumbnail->uri; ?>"/>
<br/>
<?php echo $result->title; ?>
<br/>
<a href="<?php echo $result->Thumbnail->clickUri; ?>">Flickr photo page</a>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
The return value of the tagSearch() method is a Zend_Service_Flickr_ResultSet object, which holds a collection of Zend_Service_Flickr_Result objects. Each of these objects represents a result item from the Flickr query. When the results contain photos, these are represented as Zend_Service_Flickr_Image objects. The Zend_Service_Flickr implementation will also automatically generate image URLs and page URLs from the response data (instead of requiring you to do this task manually) and then expose this data as properties of each Zend_Service_Flickr_Image object.
And that’s about it for this article. Over the last few pages, I took you on a whirlwind tour of the Flickr REST API, illustrating how it could be used with the Zend Framework’s REST client to easily integrate Flickr data and photos into a PHP application. Among the topics I covered: searching for photos by tag or group; retrieving user profile information; displaying public photos and photosets; and accessing human- and panda-tagged interesting photos. I also discussed some Flickr-specific PHP libraries, demonstrating how they can be used to perform common tasks with the Flickr API. Try them out the next time you feel the urge to write a mashup…and happy coding!
Copyright Melonfire, 2010. All rights reserved.
Categories: Zend Framework
Tags: Articles, Flickr, Intermediate, Zend_Rest_Client

