Creating RSS feeds with CakePHP and extensionless routing

Making RSS feeds and alternative content types other than HTML opens a lot of options in how your content can be used, displayed and combined. In prior version of cakePHP webservices were indicated by prefixing a url with the desired content type so an xml version of a blog index might look like xml/posts/index. This has gone the way of the pterodactyl and been replaced with a more easy to use extension based system in 1.2. If you wanted to get an xml version of posts/index in cakePHP 1.2 you can simply append the desired extension .rss making your URL posts/index.rss. Before we jump to far ahead trying to get our webservice up and running we need to do a few things. First parseExtensions needs to be activated, this is done in app/config/routes.php

Show Plain Text
  1. Router::parseExtensions('rss');

Secondly its a good idea to add RequestHandler to you $components array. This will allow a lot of cake automagic to occur. In the call above I’ve activated the .rss extension. When using Router::parseExtensions() you can pass as many arguments or extensions as you want. This will activate each extension/content-type for use in your application. Now when the address posts/index.rss is requested you will get an xml version of your posts/index. However, first we need to make the view files that will create our rss/xml feed.

The View of RSS

Before we can make an RSS version of our posts/index we need to get a few things in order. First we need to create an rss layout. We’ll put that file in app/view/layouts/rss and call it default.ctp.

Mine looks like this

Show Plain Text
  1. <?php echo $rss->header(); ?>
  2. <?xml-stylesheet type="text/xsl" href="<?php echo $rss->webroot('css/feed.xsl') ?>" ?>
  3. <?php
  4. $channelEl = $rss->channel(array(), $channel, $items);
  5.  
  6. echo $rss->document(array(), $channelEl);
  7. ?>

Update: Thought I would show what normally goes into a channel element as well.

Show Plain Text
  1. $channel = array('title' => 'Recent Writing | Mark Story',
  2.                 'link' => '/posts/rss',
  3.                 'url' => '/posts/rss',
  4.                 'description' => 'Recent writing and musings of Mark Story',
  5.                 'language' => 'en-us',
  6.                 'managing-editor' => 'no-spam@my-domain.com',
  7.             );

You might have noticed a reference to a feed.xsl checkback for more on that. This is a basic layout that accepts a set of fairly self explanatory variables. Next up is the actual view for posts/index. Again we need a separate view file so create app/views/posts/rss/index.ctp my file ended up looking like this.

Show Plain Text
  1. <?php
  2. /**
  3. * Callback used by RssHelper::items()
  4. */
  5. function rss_transform($item) {
  6.     return array('title' => $item['Post']['title'],
  7.                 'link' => '/posts/view/'.$item['Post']['slug'],
  8.                 'guid' => '/posts/view/'.$item['Post']['slug'],
  9.                 'description' => strip_tags($item['Post']['abstract']),
  10.                 'pubDate' => $item['Post']['created'],             
  11.                 );
  12. }
  13.  
  14.  $this->set('items',  $rss->items($posts, 'rss_transform'));
  15. ?>

Now we never added the RssHelper to the $helpers array nor do we have to. Since we are using the RequestHandler component, whenever an extension based request is made, the proper helper if available is automatically available for use in your views. So there you have it. A simple quick and easy way to create an RSS feed out of anything really.

Alternative Routing

Currently you can get to the new feed at /posts/index.rss. But what if we want a different url, because we just want to or we are dealing with integrating to an existing URL structure or legacy site. For example we want to use /posts/feed for our newly baked rss feed. We can set up a route like this.

Show Plain Text
  1. Router::connect('/posts/feed', array('controller' => 'posts',
  2.                                      'action' => 'index',
  3.                                      'url' => array('ext' => 'rss')
  4.                                 ) );

The feed is now accessible at /posts/feed I hope you’ve found this helpful, if you have any problems post a comment and I do the best I can to answer your questions.

Update: after reading the RssHelper source a bit better there is a cleaner way to do what I had done above. I’ve changed the code sample to reflect the updates.

Comments

Great stuff, I try to implement it in my side but getting error:
syntax error, unexpected T_STRING in C:\xampp\htdocs\tdb_prod2\app\views\layouts\rss\default.ctp on line 3

its in view file, what all wrong here, and also want to know changes we have to made in controller function.

Cheers

anonymous user on 9/2/08

Saik: If you are using my layout verbatim with the xsl sheet reference, it is quite probable that you have short_tags turned on in your php.ini. If so, you have to echo out all the xml opening <? and ?>. Otherwise PHP will interpret them as PHP.

mark story on 9/2/08

Hey Mark,

When you mention the view for the action index of the PostsController, shouldn’t the path for such view be app/views/posts/rss/index.ctp and not app/views/rss/index.ctp ?

Cheers,
Gus

anonymous user on 9/14/08

Gustavo Carreno: You are correct, I’ve corrected it thanks!

mark story on 9/14/08

Hi Mark,

thanks a lot, this has helped me an awful lot.

Quick question…I’ve used the ‘alternative routing’ like you outlined above. It all works fine, but only when I append .rss to the URL.

Any ideas of what the cause may be?

Thanks a lot.

P.S. Happy Mark Story Day ;)

anonymous user on 10/3/08

Thank you for an example, it really helps.

I’m already getting used to the idea, that everything I need Cake HAS :) I have a need for RSS feed and I was like: “Let’s try to enter it into cake API” and it didn’t disappoint me.

anonymous user on 10/7/08

Great walkthru!
I’ve followed your instructions for creating a feed inside an already working controller and it seems as though the feed is working.
When I view the feed I’m forced to download it, however.
Do I need to do anything special for it to open in FireFox’s RSS Subscription screen?

Thanks

anonymous user on 11/10/08

hi have done all the above specified steps, but i’m facing a problem using the rss feeds, when i click on the link for rss it takes me to google reader, right now working on localhost, so i installed a reader [feedDeamon] and tried to get back feeds but nothing happens when i click on the rss link,
any ideas..

anonymous user on 11/23/08

In the callback function how can I use html, text or any other helpers?

gurde on 2/22/09

gurde: You don’t. One of the downsides of using a callback is that you loose access to the other helpers. However, Daniel Feinberg at CakeDC has an article explaining how to make RSS feeds without using a callback

mark story on 2/22/09

Thanks for the tutorial, my feed works well now except that the channel title shows as: http://mywebsiteurl.com/rss/ – and I cannot seem to change it (so I don’t think it is even reading the channel parameters). Any ideas? Cheers

Sean on 6/16/09

First of all,I’m a complete noob.

I started to follow your tutorials because they made the most sense to me.

I now however have an error I do not understand.

Undefined variable: channel [APP/views/layouts/rss/default.ctp, line 4]

Can you help me?

Coen on 10/15/09

Hello,

Can you confirm if routing to a specified extension, as set in the following codesnippet, still works in CakePHP 1.3 (RC1)?
Router::connect(’/posts/feed’, array(‘controller’ => ‘posts’, ‘action’ => ‘index’, ‘url’ => array(‘ext’ => ‘rss’)) );

I implemented it without any succes, so far.

Thanx. Gilles

Gilles on 3/10/10

Giles: It should, I’m still using that route for this site. But I did have to turn Router::parseExtensions() off.

mark story on 3/20/10

Thanx. Removing that line indeed solved my problem.

Gilles on 4/6/10

I had created xml file for my one page according to cakephp http://book.cakephp.org/1.3/en/view/1461/Creating-an-RSS-feed-with-the-RssHelper….Its successfull generated xml code for me and….And my doubt is how can i make my XML code as http://mark-story.com/posts/rss i mean with HTNL styling in it..Thanks in advance

jafar on 2/6/12

I am able to create rss feed on my application. ie. if I do http://localhost/cakephp/posts.rss, this show me the feed values. Now I want to show this feed in the different website made in cakephp. How can i do that ?

Chirayu on 9/26/12

Comments are not open at this time.