I'm currently working on a project that involves pulling photos randomly. While my initial programmer instinct tells me I should write something that would enable my client to upload photos locally. However, there are some missed social networking opportunities when you decide to host your own images.
By putting the photos on Flickr, my client can keep posting photos and build a pool of images that other people can contribute to. From a development perspective, all I needed to do was leverage the Zend_Service_Flickr classes and write a simple wrapper.
The frontend page looks like this:
$randomPhotos = new RandomPhotosFromFlickr('YOUR_API_KEY'); $numberOfPhotos = 3; echo " <h2>Group Photos</h2> "; foreach($randomPhotos->FromGroup($numberOfPhotos, "GROUP@ID") as $p) echo "<img src='".$p->Small->uri."' />"; echo " <h2>User's Photos</h2> "; foreach($randomPhotos->FromUser($numberOfPhotos, "user@yahoo.com") as $p) echo "<img src='".$p->Small->uri."' />";
In this example, $p is a Zend_Service_Flickr object, so you can pull any kind of data while letting the simple class I wrote handle the selection of random photos:
class RandomPhotosFromFlickr { /** * API key for Flickr * * @var string */ protected $apiKey; /** * photoset used for retrieving random photos * * @var Zend_Service_Flickr_ResultSet */ protected $currentPhotoset; /** * number of photos in the current photoset * * @var integer */ protected $totalPhotoCount; /** * Class constructor * We need your Flickr API Key * Go to http://www.flickr.com/services/api/keys/apply/ to get one * @param string $apiKey */ public function __construct($apiKey) { $this->apiKey = $apiKey; } /** * Supply a username (a user's email address) and the number of photos you'd like returned * * @param integer $numberOfPhotos * @param string $username * @return Zend_Service_Flickr_ResultSet */ public function FromUser($numberOfPhotos, $username) { $flickr = new Zend_Service_Flickr($this->apiKey); $this->currentPhotoset = $flickr->userSearch($username); $this->totalPhotoCount = $this->currentPhotoset->totalResultsAvailable; $this->currentPhotoset = $flickr->userSearch($username, array('per_page' => $this->totalPhotoCount)); return $this->getPhotosFromCurrentPhotoset($numberOfPhotos); } /** * Supply a group ID and the number of photos you'd like returned * * @param integer $numberOfPhotos * @param string $groupId * @return Zend_Service_Flickr_ResultSet */ public function FromGroup($numberOfPhotos, $groupId) { $flickr = new Zend_Service_Flickr($this->apiKey); $this->currentPhotoset = $flickr->groupPoolGetPhotos($groupId); $this->totalPhotoCount = $this->currentPhotoset->totalResultsAvailable; $this->currentPhotoset = $flickr->groupPoolGetPhotos($groupId, array('per_page' => $this->totalPhotoCount)); return $this->getPhotosFromCurrentPhotoset($numberOfPhotos); } /** * Return an integer within the photo index range * * @return integer */ private function getRandomPhotoIndex() { return rand(0 , ($this->totalPhotoCount - 1)); } /** * Get a photo object from the Flickr Web Service * Provide an indice from the current photo set * * @param integer $index * @return Zend_Service_Flickr_Image */ private function getPhoto($index) { $this->currentPhotoset->seek($index); return $this->currentPhotoset->current(); } /** * using $this->currentPhotoset, grab a collection of random photos * * @param integer $numberOfPhotos * @return Zend_Service_Flickr_ResultSet */ private function getPhotosFromCurrentPhotoset($numberOfPhotos) { // first collect up a list of IDs (making sure there are no duplicates $photoIds = array(); while(count($photoIds) < $numberOfPhotos) { $id = $this->getRandomPhotoIndex(); if (! in_array($id, $photoIds)) $photoIds[] = $id; } $randomPhotos = array(); // query the web service to grab the photo objects foreach ($photoIds as $id) $randomPhotos[] = $this->getPhoto($id); return $randomPhotos; } }
you can download the full source if you'd like to try it yourself. Please note that I've omitted bundling my code with a copy of the Zend Framework.
Using Zend Framework's Zend_Service_Flickr
{ 3 comments… read them below or add one }
i can see how this would work given your one pool of items from which you’re drawing. but what if your client wanted to pull from more than one source, or if he seeks to expand his photography resources beyond that of flikr? how would you adjust the source code?
This code bit relies on the flickr web service api, luckily it’s been written in a way that you could decouple it from Flickr by re-writing the FromGroup() and FromUser() methods.
If you wanted to pull from a larger pool, then the cactory class, acting as a facade over multiple web service API’s could be leveraged. you’d also probably want an Adapter pattern to make all your image objects uniform.
Cool implementation.
The only suggestion I would give is to have a smooth inter fade between the refresh of the image collection.