Build Your Own RSS Feed Reader (Posted on March 23rd, 2013)

It's not everyday that a company with a significant market share in a sector gives up that market share. The RSS industry has seen a significant landscape change recently with Google's announcement to power down Reader. Quite a few new feed readers have sprung up recently and several existing ones have been rapidly iterating their software to handle the new influx of users. I'm personally content with using Hacker News and Reddit as my feed readers but I understand people's desire for a more customized experience.

For those that enjoy their feed readers I'm here to offer a solution that you can personalize to no end and will never go away. This post is going to go over building a feed reader in PHP and showing just how simple it can be to aggregate your news to one place where you have full control.

Building Our Feed

The process as you can imagine is pretty simple. Take a list of feeds, get the stories from each feed, sort the combination of stories by date published, then output the results. Let's start by defining our list of feeds.

<?php 
//Feed URLs
$feeds = array(
    "http://maxburstein.com/rss",
    "http://www.engadget.com/rss.xml",
    "http://www.reddit.com/r/programming/.rss",
);
?>

PHP5 comes with a great XML parser called SimpleXML. Let's go ahead and load the feed data into our parser.

//Read each feed's items
$entries = array();
foreach($feeds as $feed) {
    $xml = simplexml_load_file($feed);
    $entries = array_merge($entries, $xml->xpath("//item"));
}

The xpath method on our XML object is basically a string parser. Starting from the root of our XML data it goes down two children and get's all of the children enclosed in an item tag.

Here are the basics of how an RSS feed is structured so you can see why we need to go two children deep to access the item entries.

<rss>
    <channel>
        <title>Feed title</title>
        <link>Link where feed data is pulled from</link>
        <description>Description of feed</description>
        <item>Entry from a feed</item>
        <item>Entry from a feed</item>
        <item>Entry from a feed</item>
        <item>Entry from a feed</item>
        <item>Entry from a feed</item>
    </channel>
</rss>

Now that we have all the entries stored in an array we need to sort them. Otherwise the feeds will show up in the order we have them listed in our feeds array. All my items would be listed first, followed by all the Engadget items, followed by all the Reddit Programming items. All the items should have a pubDate tag that we can sort by. Since we've read all the feed data in as a string we have to remember to convert it to an integer for easy comparison which "strtotime" will take care of for us.

//Sort feed entries by pubDate
usort($entries, function ($feed1, $feed2) {
    return strtotime($feed2->pubDate) - strtotime($feed1->pubDate);
});

Our final step is just to output our entries. Each item will usually have at least the following attributes: title, link, and description. So let's use these to build our output.

<ul><?php
//Print all the entries
foreach($entries as $entry){
    ?>
    <li><a href="<?= $entry->link ?>"><?= $entry->title ?></a> (<?= parse_url($entry->link)['host'] ?>)
    <p><?= strftime('%m/%d/%Y %I:%M %p', strtotime($entry->pubDate)) ?></p>
    <p><?= $entry->description ?></p></li>
    <?php
}
?>
</ul>

RSS Feed Reader

That's all that's needed. You can add some CSS styling in if you want to mirror the effect of other feed readers. If you want to play around with the final source code you can fork it from this Github gist or check it out below.

Final Source Code

<html>
    <head>
        <title>RSS Feed Reader</title>
    </head>
    <body>
        <?php
        //Feed URLs
        $feeds = array(
            "http://maxburstein.com/rss",
            "http://www.engadget.com/rss.xml",
            "http://www.reddit.com/r/programming/.rss"
        );
        
        //Read each feed's items
        $entries = array();
        foreach($feeds as $feed) {
            $xml = simplexml_load_file($feed);
            $entries = array_merge($entries, $xml->xpath("//item"));
        }
        
        //Sort feed entries by pubDate
        usort($entries, function ($feed1, $feed2) {
            return strtotime($feed2->pubDate) - strtotime($feed1->pubDate);
        });
        
        ?>
        
        <ul><?php
        //Print all the entries
        foreach($entries as $entry){
            ?>
            <li><a href="<?= $entry->link ?>"><?= $entry->title ?></a> (<?= parse_url($entry->link)['host'] ?>)
            <p><?= strftime('%m/%d/%Y %I:%M %p', strtotime($entry->pubDate)) ?></p>
            <p><?= $entry->description ?></p></li>
            <?php
        }
        ?>
        </ul>
    </body>
</html>

As always if you have any feedback or questions feel free to drop them in the comments below or contact me privately on my contact page. Thanks for reading!

Tags: PHP