RSS feed aggregator/combiner in PHP

Having also a second blog, I needed a way to combine the RSS feeds into one, hence, the following code was written (well, modified from this code).

The code uses MagpieRSS to read and FeedCreator to write. Thanks to Scott Hurring for code to grab the RSS feed title.

The code has been tested with my 2 WordPress blogs (view example combined RSS feed). To install, extract and upload the feed directory and modify the settings in index.php.

Download all files and folders

Update: 1 April 2009, improved code speed up the slow response of the url_grab_title function.

Update: 3 March 2010, I have further improved the code and made it easier to intergrate into another site.
Refer to this post.

<?php
	$TMP_ROOT = "tmp/";
	$DOMAIN_NAME = "http://thydzik.com/";
	$SITE_TITLE = "thydzik";
	$SITE_DESRIPTION = "thydzik's blog feeds";
	$SITE_AUTHOR = "thydzik";
	$RSS_DIR = "../";

	$array = array(
		"http://blog.thydzik.com/feed/",
		"http://sonyaandtravis.com/feed/"
	);
	$num = 10;
	$showfullfeed = FALSE;

	define('MAGPIE_DIR', $RSS_DIR.'feed/');
	define('MAGPIE_CACHE_DIR','/'.$TMP_ROOT.'rsscache');

	/* include required files */
	@require_once(MAGPIE_DIR.'rss_fetch.inc');
	@include(MAGPIE_DIR.'feedcreator.class.php');

	/* Set RSS properties */
	$rss = new UniversalFeedCreator();
	$rss->useCached();
	$rss->title = $SITE_TITLE;
	$rss->description = $SITE_DESRIPTION;
	$rss->link = $DOMAIN_NAME;
	$rss->syndicationURL = $DOMAIN_NAME."feed/index.php";

	$i_temp = 0; //temp i variable
	$j_temp = 0; //temp j variable
	$total_temp = 0; //temp total number of posts in all rss feeds

	$array_count = count($array); //number of rss feeds

	/* code to determine which post to display */
	for ($i = 0; $i < $array_count; $i++) {
		$rss1 = fetch_rss($array[$i]);
		if ($rss1) {
			$array_temp[$i]['page_title'] = url_grab_title($array[$i]);
			$items = array_slice($rss1->items, 0);
			$array_temp[$i]['rss_data'] = $items;
			$total_temp += count($items);
			$array_temp[$i]['rss_pointer'] = 0;
			preg_match('@^(?:http://)?([^/]+)@i', $array[$i], $matches);
			$array_temp[$i]['site_url'] = $matches[0];
		}
	}
	while ($total_temp <> 0 && $num > 0){// loop while there are remaining posts to process
		$date_timestamp_temp = 0; //initialise to 0
		for ($i = 0; $i < $array_count; $i++) {
			$date_timestamp_temp = max($date_timestamp_temp, $array_temp[$i]['rss_data'][$array_temp[$i]['rss_pointer']]['date_timestamp']); //determine latest post from rss feeds
			if ($date_timestamp_temp == $array_temp[$i]['rss_data'][$array_temp[$i]['rss_pointer']]['date_timestamp']) { //latest post is found so save where it came from
				$i_temp = $i;
				$j_temp = $array_temp[$i]['rss_pointer'];
			}
		}
		$total_temp --; //decrement total remaining posts to process
		$num --; //decrement number of posts to display
		$array_temp[$i_temp]['rss_pointer'] ++; //increment post index of used post rss

		/* code to display post */
		$item = $array_temp[$i_temp]['rss_data'][$j_temp];
		$href = $item['link'];
		$title = $item['title'];
		if (!$showfullfeed) {
			$desc = $item['description'];
		}else{
			$desc =  $item['content']['encoded'];
		}
		$desc .=  '
Copyright © <a href="'.$array_temp[$i_temp]['site_url'].'">'.$array_temp[$i_temp]['page_title'].'</a>.  All Rights Reserved.
';
		$pdate = $item['pubdate'];
		$item = new FeedItem();
		$item->title = $title;
		$item->link = $href;
		$item->description = $desc;
		$item->date = $pdate;
		$item->source = $DOMAIN_NAME;
		$item->author = $SITE_AUTHOR;
		$rss->addItem($item);
	}

	function url_grab_title($rss_url) {
		$contents = file_get_contents($rss_url, TRUE, NULL, 0, 3072);
		$contents = preg_replace("/(\n|\r)/", '', $contents);
		preg_match('/<title>(.*?)<\/title>/i', $contents, $matches);
		return $matches[1];
	}

	// get your news items from other feed and display back
	$rss->saveFeed("RSS2.0", '/'.$TMP_ROOT."rsscache/feed.xml");
?>

  • James

    This code solves a problem I am having and I would like to deploy it on my system. I have only 2 questions, and I apologize I am a bit green on PHP.
    1. Can I pull in rss feeds that are hosted on 2 separate systems (wordpress.com & a Dreamhost account)
    2. Where do I place the “feed” folder? wp-includes, root, ??

    Thank you for your help and contribution to the bloggers of the world with this code.

    Best,
    James

  • thydzik

    James,

    1. It should be able to as long as the RSS feeds produced are standard RSS feeds. The Magpie RSS parser does support multiple versions of RSS feeds as well. Best thing to do would be to try it out for yourself.

    2. You should be able to put the ‘feed’ folder anywhere, make sure to put the tmp directory in the same location, i.e. if ‘feed’ folder is in the root, then the ‘tmp’ folder will need to be there to. You may need to modify the code to match your folder locations. The reason I placed the ‘feed’ folder in the root was so that I could then reference ‘http://domainname.com/feed/’ to get the RSS feed.

    Travis

  • James

    Travis,

    I wanted to thank you. I got it working. I have to use a fix from the link below (my hosting provider was blocking remote connections), but now I am up and running!

    Fix for fopen: http://pomocnik.com/users/dan/2005/10/warning-fopen-functionfopen-url-file-access-is-disabled-in-the-server-configuration/

  • Hexagon

    Is there any way to fetch only one (the latest) record per feed? So we can have a combined feed for lets say 12 xml’s in with the latest post of each xml???

  • thydzik

    Hexagon, have a look at the original code I based this on
    http://theos.in/technology/howto-combine-two-wordpress-rss-feed/

    modify the ‘foreach ($items as $item)’ to something like ‘$items[0]’ to return the first post. Note this method won’t order the posts by date.

    or you could modify the above, but will require some thought.

  • Alexwebmaster

    Hello webmaster
    I would like to share with you a link to your site
    write me here [email protected]

  • joe

    Hi,

    Is it possible that we combine the rss into one feed… I mean feed with 10 entry convert it to only 1 entry (it’s more like a diggest). Is it possible?

    Thanks

  • yes, it is possible.

    I have done 3 feeds, but you can do as many as you need. just increase the array size and add the urls.

  • Lewis

    Has anyone modified this so that it keeps the origional date/time in the new feed that is created?

  • Mtyagi

    is there any  option to sort the feed on date ?

  • ¬†Mtyagi, I should be sorted by feed date.