Thursday, September 1. 2005Flickr API FunComments
Display comments as
(Linear | Threaded)
You may interested in looking at Phlickr, an object oriented PHP 5, Flickr API kit. It also uses CURL and SimpleXML. It's pretty easy to use and well documented.
Yeah, I looked at Phlickr. It returns raw SimpleXML objects though. In order to cache responses in APC's shared memory segment without having to serialize they need to be parsed further down into arrays.
If you know what you are including and when, you shouldn't ever need to use include_once/require_once. They are also slower than doing a straight include/require.
But _once avoids possible multiple inclusions, and require prevents further execution (and whatever various error messages) if the .inc files get moved, chmod'd, etc.
How much slower are they? I never heard of any performance difference. Can't be much. BTW, nice article - I checked out flickr's API page a while ago and didn't really understand what was possible with it. Your demos help.
Why take a performance hit when none is needed. If the include files get moved around, a require_once won't fix that anyway. Always using require_once calls is just a bad habit as far as I am concerned. There may be a few common files that are prone to multiple inclusion in a complex application, but most shouldn't be included multiple times and if you are including them multiple times you'd probably want to know about it and not just ignore it the way the _once functions do.
As far as stopping execution goes, that has nothing to do with _once. That's a require vs. include thing.
I hate to argue with you about PHP ;), get all OT here, and about something pretty trivial, but I gotta disagree - other languages won't let you get past including files that can't be included. I use always use require_once, except when include_once is needed (avoids loading code that may or may not be used). This prevents scripts from trying to do who-knows-what after a failed include (which happens sometimes after upgrading, etc.), and spitting out who-knows-what to users.
There'd probably be less of a performance hit by avoiding OOP too, but the other benefits outweigh that.
Again, _once has nothing to do with what happens on a failed include. You can make a case for using require over include so you get a hard failure, but you don't always want a hard failure and in this particular example your get your hard failure right away anyway as you would end up calling a function that hasn't been defined. You also get a big fat warning that you can choose to make fatal in your error handler, so the difference is pretty minor.
> _once has nothing to do with what happens on a failed include
I know! I can't think of a case where I wouldn't want a hard failure if required (heh) files weren't included. And I would rather not rely on some other hopefully resulting error terminating the script (sometimes they can get pretty far and print out lots of warnings, errors, etc.).
Sure, if you are not using your own error handler, that is probably true. But when you do have your own error handler, it is more convenient to get a warning because you then have full control over what you can do. With an E_FATAL it doesn't matter what you do in your error handler, you are done.
I should probably write up something on error handling at some point. Perhaps something for my next long flight.
Ah, okay, you have a point there. But doesn't having your own error handler reduce performance? ;P
Sure, on an error things get slower. But I don't care about performance outside of my common codepath. On my common codepath I do however care a lot and go out of my way to make sure things are fast.
Can you elaborate on how require_once (and require too?) hits performance? That's the first I've heard of it. I can't imagine it's much. I didn't see anything in the docs, except for a comment suggesting using a wrapper class(!) instead.
The _once functions have more work to do. I never said require was slower than include. The two are pretty much identical in the code. But the _once functions are slower. The beauty of open source is that it doesn't matter what the docs say, nor what you hear, you have the source code and the definitive answer at your fingertips:
http://cvs.php.net/co.php/ZendEngine2/zend_vm_def.h?r=1.59.2.5#2666 include/require is a one-liner. include_once/require_once need to fiddle around with the included_files hash. Easy enough to benchmark. Take a little script that just does: < ?php include 'inc.inc';? > And in inc.inc we have: This is a test < ?php echo "Hello World"? > This is a test On one of my boxes I get: 10000 fetches, 5 max parallel, 410000 bytes, in 8.60147 seconds 41 mean bytes/connection 1162.59 fetches/sec, 47666.2 bytes/sec msecs/connect: 0.263676 mean, 20.707 max, 0.109 min msecs/first-response: 3.88822 mean, 1987.42 max, 0.722 min HTTP response codes: code 200 -- 10000 Then change inc.php to use require_once instead and I get: 10000 fetches, 5 max parallel, 410000 bytes, in 9.1419 seconds 41 mean bytes/connection 1093.86 fetches/sec, 44848.4 bytes/sec msecs/connect: 0.27873 mean, 33.92 max, 0.11 min msecs/first-response: 4.12044 mean, 369.463 max, 0.741 min HTTP response codes: code 200 -- 10000 Running it a few times back and forth the require_once is always 55 to 75 requests per second slower than a straight require. Of course, in a test that does nothing else, the effect is magnified and pales in comparison to an SQL query or anything real. It is unlikely to ever be your bottleneck, but that doesn't change the fact that it is slower. Whether it is measurable in your system is something you will have to test for yourself.
> and pales in comparison to an SQL query or anything real
Absolutely. Does the performance difference of include vs. require_once make any difference to most everybody in real world situations? I doubt anybody, but perhaps Yahoo, would have traffic at those levels where it might make a difference. But they also have money to just add more hardware too ;). There are many many other factors that tweaking would bring result in performance improvements. I'm reminded of the last slide of your "Why PHP?" presentation (which I can't seem to find online anymore): Don't spend all your time optimizing every last thing - there's a point of diminishing returns (paraphasing). I also mostly use double quotes instead of single quotes, even when vars aren't inserted or strings could be concatenated together, even though I've heard single quotes are marginally faster. I find double quotes more convenient and readable. I mostly just worry about optimizing database queries - they're the lion's share of performance bottlenecks. And REST/SOAP calls. Beyond that, almost nobody will notice any benefit from additional performance tweaks.
Hi, any chance of you sharing your Gallery to Flickr migration tool with me/us/the world? I'm about to do exactly that and I'd love to have it automated!! I'm good with code/php/whatever so it'd be fine if you didn't want to support it or anything.
Thanks!
I've thought about this, and will continue to use include_once and require_once, and think the arguments against it are really weak. Any performance impact is negligible. And it's really really bad form to let your code continue to execute past errors.
Depends on your scale and your OS. An extra open() syscall (when using an opcode cache) for every include can add up quickly.
Hi, maybe I'm an idiot put have you made the dependencies for your demo files (aka secrets.inc and flickr_api.inc) available to download?
I'm lost--please help me!
It's one of the first links in the article:
http://lerdorf.com/php/flickr_api.phps And I explain what should be in the secrets file: $secrets = array('api_key'=>'your_key_here','api_secret'=>'your_secret');
hi,
i just downloaded the api and played around with it - very nice, thanks! i now use it to display a random selection of my flickr favorites on my site. check it out here: http://me.phillipoertel.com the source: http://me.phillipoertel.com/downloads/flickr_favorites.zip
I've been enjoying your beautiful adaptation.
Q: How can I edit that will random display from my own Flickr photos? Thankx in advance, Arthur
Hey Rasmus - You don't have to prefix your private variables with underscores anymore! ;)
It's habit. That way I know they are internal as I use them without having to hunt for the declaration.
Well, I finally got a chance to try this out. Mega kudos for making it crystal clear. Your wrapper classes work great so far. Only issue I came across is the getPhotoURL function - no "_{size}" suffix is added for medium (
Whoa, looks like last part of my comment got stripped. It was:
< 500 pixels) images. BTW, great to see that APC has been updated to work with PHP 5. Last I checked, none of the other caches had been updated to work with PHP 5.
I changed that function to:
function getPhotoURL($p, $size='s', $ext='jpg') { if(empty($size)) { return "http://photos{$p['server']}.flickr.com/{$p['id']}_{$p['secret']}.{$ext}"; } else { return "http://photos{$p['server']}.flickr.com/{$p['id']}{$p['secret']}{$size}.{$ext}"; } }
I added a couple function I found useful:
// A really powerful and useful function function photosSearch($user_id='', $tags='', $tag_mode='', $text='', $min_upload_date='', $max_upload_date='', $min_taken_date='', $max_taken_date='', $license='', $extras='', $per_page='', $page_sort='') { $params = array( 'user_id' => $user_id, 'tags' => $tags, 'tag_mode' => $tag_mode, 'text' => $text, 'min_upload_date' => $min_upload_date, 'max_upload_date' => $max_upload_date, 'min_taken_date' => $min_taken_date, 'max_taken_date' => $max_taken_date, 'license' => $license, 'extras' => $extras, 'per_page' => $per_page, 'page_sort' => $page_sort, ); $xml = $this->callMethod('flickr.photos.Search',$params); if(!$xml) { return FALSE; } foreach($xml->photos->attributes() as $k=>$v) { $ret[$k] = (string)$v; } $i=0; foreach($xml->photos->photo as $photo) { foreach($photo->attributes() as $k=>$v) { $ret['photos'][(string)$photo['id']][$k] = (string)$v; } $i++; } return $ret; } function urlsGetUserProfile($user_id) { $params = array('user_id'=>$user_id); $xml = $this->callMethod('flickr.urls.GetUserProfile',$params); if(!$xml) { return FALSE; } $attr = $xml->user->attributes(); return (string)$attr['url']; }
Hey Rasmus, thanks for creating this - its a cool toy! Also gave me an excuse to install PHP5 on my server.
Here's a simple update to get data on photosizes - function getPhotoSizes($id) { $params = array('photo_id'=>$id); $xml = $this->callMethod('flickr.photos.getSizes',$params); if(!$xml) { return FALSE; } $i=0; foreach($xml->sizes->size as $size) { foreach($size->attributes() as $k=>$v) { $ret[$i][$k] = (string)$v; } $i++; } return $ret; } Your output loop could do something like this - foreach($photos['photos'] as $photo) { $sizes = $flickr->getPhotoSizes($photo['id']); if (is_array($sizes)) { foreach($sizes as $size) { print ''; } } }
Hey Rasmus,
I paid a guy to do me a gallery2flickr type-o-script to transfer all my 3500+ pics from Gallery to Flickr. If your interested, please check it out here: http://www.in-duce.net/archives/migration_from_gallery_to_flickr.php cheers.
Hi,
This is everso slightly off-topic - as I am not using this API php, but parsing the basic flickr RSS. eg: http://www.flickr.com/services/feeds/photos_public.gne?tags=cats&format=rss_200 But, I'm going completely mad here, trying to use SimpleXML to extract the media:thumbnail url attribute of the Flickr RSS feed, which uses the 'media' namespace located at http://search.yahoo.com/mrss/ (in the xmlns tag) I can parse the feed OK, but when it comes to getting the thumbmail url, I tried this: ...where $feeditem is the name assigned while looping the items with a foreach: $media = $feeditem->children("http://search.yahoo.com/mrss/"); $thumb = $media->thumbnail['url']; but I don't get anything out??? :( I was finding all this SimpleXML really easy to grasp and very, very welcome with alot of work I'm doing with OPML and RSS, but this has me foxed. If anyone could be of any assistance at all, I would be truly grateful - and I'll doc it too ;) eg: < rss > < channel > < item > < media:thumbnail url="http://etc.etc.etc" / > < /item > < channel > < /rss > many thanks for a wonderful new version of PHP! Cheers, Kosso
You could just use my RSS parser:
http://www.lerdorf.com/php/simple_rss.phps Or look through the code to see how I solved the namespace problem.
HI,
Thanks for that, but it kind of does alot more than I need ;) However, I did manage to get the url attribute I need while looping the channel->item as $feeditem with $thumburl = $feeditem->children('http://search.yahoo.com/mrss')->content->attributes(); though, oddly the attributes() only throws back one value, the url, but not the other two attributes, height and witdh from: < media:thumbnail url="http://flickr.com/etc/etc/yada/yada.jpg" height="75" width="75" / > surely there should be 3? great parser you have there though ;) thx. Kosso
sorry, that was meant to be:
$thumbnail = $feeditem->children('http://search.yahoo.com/mrss')->thumbnail->attributes(); |
Why a toys page?I love geeky toys and people are always asking me about them. So this page is where I keep track of the gadgets that interest me.
QuicksearchMy LinksPopular EntriesTemplate dropdownBlog AdministrationCreative Commons |
Rasmus Lerdorf has posted Flickr API Fun. I like stuff I can pick up and do something useful with in an hour or two. Perhaps my attention span is too short, but if I have to read a 300 page...
Tracked: Sep 01, 13:14