Recently I updated the site so that it would summarize the latest posts
from my blog. The motive is simple: my site does not get updated often,
so data should be piped in from elsewhere to reassure people that I have
not died in the middle of writing Parrot Babystep 09.
The blog summary works. It’s nice. It’s pretty. Well, it’s pretty enough
for me. The problem is that I am not the world’s most prolific blogger.
I can write a lot, and I can write a little. The in-between world of
blogs is uncomfortable territory for me. As a result, that nifty little
summary only makes me look a little bit less dead than the old static
update system I used.
What about a Twitter feed? That is easy enough,
but the problem with Twitter feeds is that you get no context. I might
be teasing a fellow Tweeter with foursquare
jokes, but if you don’t know him and his seething hatred of all things
foursquare then my commentary will seem nonsensical at best.
Besides, I haven’t been using Twitter quite as much recently. I’m on to
the next shiny thing: Google
Buzz. It provides the
instant gratification of Twitter, along with a system for commenting,
liking, geolocation, sharing links, and more. It’s sort of like
Facebook, except that it’s embedded into GMail
and there’s no Mafia Wars yet.
I’ve been buzzing rather
frequently. I even
have my blog and Flickr
activity fed into Buzz, so my Buzz stream includes anything from either
of those.
How?
Let me throw an immediate disclaimer by saying that 80% of what I want
is already implemented in the Google Buzz
Widget,
a jQuery plugin which displays the contents of your Buzz stream. I tried
it out, and it worked like a charm.
A little CSS fiddling, and voila!
The only thing is that some stuff I really want sits in the other 20%:
the (admittedly lightweight) formatting from the original Buzz
the links I share
the images I post to Flickr.
I don’t blame the Google Buzz Widget for not having that information. It
uses a Google service which does not yet provide those details. To get
at that information today I’ll need to directly access the original
feed, not the feed as translated by a service. Since I’m the sort of guy
that enjoys reinventing wheels, I’ll put something together myself.
My site runs on a shared host, and the freshest language available to me
on that host is PHP. I’m not a huge fan of the
language, but I am pragmatic. If the most convenient tool available is
PHP, then that’s what I’ll use.
If they had mod_perlite, it would be a
significantly different story. Oh well. Let’s begin.
Start!
The initial local development will be on the home Mac, running OS X 10.5
and PHP 5.2.11. My Web host supports newer versions of PHP - all the way
up to 6 -but I’m not going to worry about it today.
Grab my own copy of the feed
All right. I know for a fact that I’m going to be loading and
manipulating this data a lot during the initial stage of development.
I might as well grab a copy of the Buzz XML feed and work with it
locally. That will save a bit of time and network load. Hey, every
second counts.
Buzz feed URLs follow a simple pattern, with your username inserted at
the approproate place.
The first task is to parse the XML and display the results. I enjoy
SimpleXML when handling
XML in PHP-land, since it hands back a reasonable data structure without
any fuss from me.
The result is not exciting, but it does show that the XML is being
parsed. I have created a simple dump function which will come in handy
as I examine the information being displayed.
Show Entries
Now I want to display the entries. How about I start by dumping them?
This lets me focus on the structure of an entry, at least as far as
SimpleXML perceives it.
Quite a few details are being missed because SimpleXML has its own
special tricks for handling namespaces, but a lot can be done before
that is a concern. Let’s look at the information that is readily
accessible and figure out what I can do with it.
title
The posting source is shown here (Buzz, Flickr, Mobile, etc.)
published
When the Buzz was posted
link
A collection of links associated with the buzz (the buzz itself,
posted links, images, replies, etc.)
content
The Buzz, formatted as an HTML fragment
Let’s do some simple formatting. I’m not sure what to do with the links
yet, so I’ll just dump them.
So what does that get us?
This particular example has three links.
An HTML “alternate” link that goes to the original Buzz post.
An image “enclosure” link that leads to the Flickr
photo.
An Atom “replies” link that leads to a feed of replies for the
original post.
I care about the alternate and enclosure links, but not about the
replies. Now, every entry has an alternate link, but not all of them
have enclosure links. I will need to do a little processing to display
those links properly, but I don’t want that processing to occur down
there in the display section. I like to keep my displays as simple as
possible. I’m going to create a Buzz_Entry class to handle the hard
work.
The first stab at this class is going to be simple, just adding clearly
defined links for the Buzz and any enclosure.
The newest iteration of the main file builds a collection of Buzz_Entry
objects and takes advantage of the new attributes.
Hey look! Now there’s stuff you can click!
I want to refactor a little bit now, and put that initial logic into a
separate file. It’s nice to keep your workplace tidy.
This makes the initial PHP block of the main file simple.
Now that I’ve satisfied my general sense of tidiness for the moment, I
want to make the “published” timestamp into something normal people can
read.
It’s a good idea to set the time zone, especially if your “published”
format includes the time. I set mine in Buzz.inc.php.
Now I don’t have to work so hard to figure out when a particular Buzz
was posted.
I want to make one more adjustment to the output. The phrase “Buzz by
Brian Wisti from X” in every title is redundant. “X” is the important
part. Let’s get rid of the title, and replace it with a source.
I can’t forget to change the reference in the main PHP file.
Better?
Yes. Each entry now has what I consider a comfortable amount of
information. Sure, I would love to embed the image into the entry, but
that can wait. At least the link to the image is being displayed.
Besides, if I wait too long the Buzz API will cover all of this. I want
something up today.
Now that I have the information I want, it’s time to make the entries
pretty with a little shuffling and some CSS.
Here are the style rules that I used.
And the result may not be pretty, but it’s definitely better looking
than it was before.
Live Data
Most of my fiddling is done. It is time to use live data. On the home
machine, I only need to change the value of $source, because I have
allow_url_fopen
enabled.
However, more is needed for this to work on the shared host.
allow_url_fopen is not available, but the PHP cURL
functions are. Well, we work
with what we have.
Most of you can stop right here, but I need to do one more step. This
site is actually a bunch of static HTML content, with no server side
interaction. Well, almost static. I give myself permission to include
content feeds from supplemental files and sites via JavaScript.
It’s my site, and I go by my own strange rules. At least I try to be
consistent.
I’m going to do some quick and dirty
AJAX. Very quick,
and very dirty. Let’s change the main buzz.php file so that it generates
an HTML fragment rather than a whole valid page.
I will continue using jQuery as the framework for
JavaScript interaction at this site, because it’s familiar to me.
Off in my site JavaScript file cnh.js, I set up the buzz-loading
function. All it does is grab the output from buzz.php and insert it
into the document.
Finally, I add the function call to my site index:
Hopefully you can now go to the home page and see a Buzz feed!
Okay, one issue. It’s showing the whole feed. Let’s throw in a limit
to the number of entries returned. I don’t feel like messing with the
calling code right now, so let’s have a reasonable default.
Okay. That’s a good enough hack for a low-traffic site like mine.
Cache the Output
What would happen if I got twelve million hits per minute because the
world had suddenly become obsessed over whether I would ever finish
knitting those socks?
Well, my educated guess is that coolnamehere.com would be hosed. I have
a good host for the price, but I think that is more traffic than your
average shared host would be prepared for.
I can take precautions to reduce the load, though. One that comes to
mind is caching the HTML output to a file, and only checking for updates
every 30 minutes or so. That will involve using PHP’s output control
functions to store the
output which would normally be printed.
I’m putting the display block into a template file, to make the
application flow a little easier to understand. The display block does
get an additional item to tell me when the cache was last built.
The main buzz.php looks a bit different now. Instead of jumping
straight to the display, it looks for a cache file. If the cache file is
new enough -defined here as less than 30 minutes old - then the script
goes the easy way out and loads the cache. Otherwise, it buffers the
output into a string, which is then saved to the cache file.
Oh right. Whatever the output was gets sent to the browser. Don’t want
to forget about that.
Sweet. It worked. I make a couple minor adjustments relevant to my
shared host settings, upload what I have, and hope for the best.
A Quick Bug Fix
One issue is that the output gets displayed twice when the cache is
first built.
The problem is that I’m building $output by capturing standard output,
and then printing out $output. What I didn’t stop to think about is
the fact that standard output still gets displayed when the script is
done running.
Okay, so a quick fix is to only display output when it’s loaded from the
cache file.
Next Steps
There is a lot more information in the XML that I haven’t used with my
naive application of SimpleXML. Once my eyes have uncrossed from this
quick burst of activity, I’ll want to figure out how to get at those
details and incorporate them into the feed.