Monday 21 April 2008

Reading RSS (XML) feeds in PHP5 - Part 2

After adding my blog as a news feed last week, I decided it would be much tidier to restrict the number of blog entries on each page . This should reduce time to render the page, and most blog entries that are read will be the more recent ones anyway. The inclusion of Next/Previous buttons would still allow the reader to navigate through other blog posts.

Clearly, the page request would have to be processed seperately for each batch of posts, so this requires some changes to the page that calls the underlying function. The new inline page PHP code looks like this:

$nEntriesPerPage = 5;
$blogIndex = (int) $_GET["index"];
$foo = doShowBlogSections($blogs[0], $blogIndex, $nEntriesPerPage);

The number of entries to be show per page is 5 and by casting the index to an integer, if it isnt passed through by the page, we default it to zero.
Next Up is the function itself, the doShowBlogSections call does this:

function doShowBlogSections($blogURL, $blogEntryIndex, $nBlogEntries) {
// get rss feed contents
$library = @simplexml_load_file($blogURL);
$i=0;

// loop over each entry and output if relevant and possible
$needNextButton = false;
foreach ($library->entry as $entry) {
// only show nBlogEntries...if we exit the loop normally, no next button required
if ( ($i) == ($nBlogEntries+$blogEntryIndex) ) {
$needNextButton = true; // having to bail - there are more entries available
break;
}
// only output blog entries from blogEntryIndex onwards
if ($i >= $blogEntryIndex ) {
echo "<p>";
echo "Title: ".$entry->title."<br />\n";
$pubDate = $entry->published;
// sort out obscure date format used by blogger.com
if ( $pubDate = strtotime($pubDate) ) {
// we have a valid unix timestamp value from the date string
$pubDate = date("F j, Y, g:i a", $pubDate);
echo "Published on ".$pubDate."</p>\n";
}
else {
// give up and just output in whatever format the date/time is in
echo "Published on ".$entry->published."</p>\n";
}
echo "<div>".$entry->content."</div>\n";
}
$i++;
}

// Provide suitable Next and Previous buttons
if ( $blogEntryIndex == 0 ) $needPreviousButton = false;
else $needPreviousButton = true;
$blogPreviousIndex = $blogEntryIndex - 5;
if ($blogPreviousIndex < 0 ) $blogPreviousIndex = 0;
$blogNextIndex = $i;

$thisPage = $_SERVER['PHP_SELF']; // need to be self referencing for page name
echo "<p>";
if ($needPreviousButton) echo "<a href=".$thisPage."?index=".$blogPreviousIndex."><<< Previous</a>";
if ($needPreviousButton && $needNextButton) echo '      ';
if ($needNextButton) echo "<a href=".$thisPage."?index=".$blogNextIndex.">Next >>></a>";
echo "</p>";

}

It should be fairly self explanatory as the code has a liberal sprinkling of comments. Other enhancements that I may add at a a later date include:

  • First and Last buttons

  • Some indication of total number of log entries and where you are in that list

  • a list of blog entry titles and dates as clickable links

  • a link to the comment page

Friday 18 April 2008

Reading RSS (XML) feeds in PHP5 - Part 1

Another new addition to the website, is the reading in of RSS feeds from my blogs. This seemed much harder than it actually was, especially was I got my head around the built in PHP5 XML functions. In essence, you just call @simplexml_load_file("the_xml_url") and the loop over each entry. The hardest part is working out what the section names are within the xml file, and you can just load the XML into a text editor to find out. The code I am using goes as follows:


function doSimpleShowBlog($blogURL) {
// get rss feed contents
$library = @simplexml_load_file($blogURL);
// loop over each entry
foreach ($library->entry as $entry) {
echo "<p>";
echo "Title: ".$entry->title."<br />\n";
echo "Published: ".$entry->published."</p>\n";
echo "<div>".$entry->content."</div>\n";
}
}

Simple huh! Some error checking and so on is recommended but this works for me. An example can be found here.

Tuesday 15 April 2008

New website

Well, my new website is up and running (www.birkbeck.org.uk) using a modified version of the Satellite v1.5 PHP scripts. As time goes on, I will be adding functionality - including feeds from this and other blogs of mine - and finally taking some time out to learn some PHP.

Most recently, I have been working to get a Flickr Tag Cloud working in a way I like. The original scaled the font according to the number of occurrences of each tag, but the distribution of occurrences was very wide - for instance, most images are tagged with England, Britain and UK. The order of magnitude difference between the most used tags and the majority of tags is very large and the way it had been coded meant that only those tags used in approx 70% or more of the photos in my stream were shown in anything other than the smallest font. The code below is a snippet I have added to calculate font sizes based on a normalised distribution of occurrences.


// Calc font size for a normalised distribution........
// First build array of total counts for each tag count
$i = 0;
foreach ($theCount as $count) { $tagCounter[$i] = $count; $i++; }
// sort array of counts
sort($tagCounter);
// Remove duplicates
$sortedTagCounts = array_unique($tagCounter);
// create an array of preset font sizes determine by tag count
$totalTags = count($sortedTagCounts);
$fontRange = $maxFontSize - $minFontSize;
$fontSizeMultiplier = (($fontRange-$minFontSize+1)/$totalTags);
$i=0;
foreach ($sortedTagCounts as $tagOccurrence) {
$tagOccurrencesMappedToFontSizes[$tagOccurrence] = $i*$fontSizeMultiplier)+$minFontSize;
$i++;
}


In essence, I create a sorted list of tag occurrence frequencies, e.g. one tag may occur 8 times, another may be used over 1000 times. In all, there may be 50 different occurrence numbers. If two different tags are used 10 times each, then this is one entry in the list. Then, I created an array based on each number of occurrences that holds the font size.

Later in the code (not shown here), when I loop through the tags I just use the occurrence frequency as an index into the array of font sizes. There may be easier ways to accomplish this, but I am reasonable happy with it, particularly given my lack of knowledge regarding PHP syntax and built-in functions.

I am working on a revised version of the code and plan to release the full source code, once I have added integral blog pages, but first need to write some PHP to feed that in via XML and RSS. In the meantime, if you want a copy of the code, drop me an email.