Using RSS feeds is a commonly used way of distributing your news headlines to the world. The users will be able to see all the latest headlines or snippets of the latest headlines without actually visiting the page. I think that RSS feeds are great, and in combination with eg Firefox's live bookmarks it is very easy to quickly get an overview of the latest headlines of your favorite news websites.

Now, how do you make those RSS feeds in an automated way without having to manually create them each time you submit a new article to your website? With PHP that is very easy and can be done in under 70 lines (including the configuration file).

The database data
First we will need some data to get the contents to our RSS feed from. We will pretend we have a news application that consists of two database tables: authors and news

Code:
CREATE TABLE authors (  
  aid tinyint(11) NOT NULL,  
  a_name varchar(255) NOT NULL,  
  a_email varchar(255) NOT NULL,  
  UNIQUE KEY aid (aid)  
) TYPE=MyISAM;  

INSERT INTO authors (aid, a_name, a_email) VALUES (1, 'Author 1', 'author1@example.com'),  
(2, 'Author 2', 'author2@example.com');  

CREATE TABLE news (  
  nid tinyint(11) NOT NULL,  
  n_author_id tinyint(11) NOT NULL,  
  n_title varchar(100) NOT NULL,  
  n_body text NOT NULL,  
  n_time int(32) NOT NULL,  
  UNIQUE KEY id (nid),  
  FULLTEXT KEY title (n_title,n_body)  
) TYPE=MyISAM;  

INSERT INTO news (nid, n_author_id, n_title, n_body, n_time) VALUES (1, 1, 'Test headline', 'This is just a test headline.', 1160579948),  
(2, 1, 'Another headline', 'This is just to test the RSS generator.', 1160580547),  
(3, 2, 'Bla bla bla', 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi commodo enim. Quisque nisi neque, sodales sed, egestas sit amet, pharetra quis, nibh. Proin non nunc. Morbi aliquet quam. Donec tincidunt libero id purus. In id ipsum ut orci iaculis sodales. Nulla suscipit. Phasellus ac sapien. Phasellus id nisi non elit tincidunt euismod. Sed porta. Suspendisse potenti. Ut euismod risus. Sed tempor metus suscipit ipsum. Nunc dapibus. Vestibulum ipsum nisi, scelerisque ac, porttitor feugiat, vestibulum in, augue. Sed volutpat dui in nulla fringilla ornare.rnrnVivamus turpis mi, scelerisque non, pulvinar a, dictum vitae, purus. Sed tempor tincidunt purus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus cursus eros. Vivamus suscipit vulputate velit. Mauris vestibulum augue eget mauris eleifend lobortis. Pellentesque enim risus, congue et, sodales nec, blandit eget, lacus. Ut viverra. Ut ultrices scelerisque nisl. Praesent lorem nibh, suscipit at, tincidunt sit amet, iaculis vel, nisl. Praesent ac nisl. Integer vitae magna ac tellus dictum tincidunt. Proin velit diam, posuere non, sodales in, pretium at, lorem. Ut lacinia placerat felis. Donec convallis malesuada magna.rn', 1160580604);
Full application code
I will start by giving you the full code to the application and then I will explain it on the following pages. We will begin with the configuration file (config.php):
PHP Code:
<?php  
$config 
= array(  
'db_host'            => "localhost",  
'db_user'            => "root",  
'db_pass'            => "",  
'db_name'            => "news_articles",  

'language'            => "en-us",  
'feed_title'        => "Example.com Headlines",  
'link'                => "http://example.com",  
'description'        => "The latest news of example.com",  
'copyright'            => "{year} Example.com - All Rights Reserved",  
'show_feed_pubdate'    => false,  
'headlines'            => 0,  
'show_author_info'    => true,  
'encoding'            => "ISO-8859-1",  
);  
?>
Then we will have the actual application (rss.php):

PHP Code:
<?php  
include "config.php";  

$link mysql_connect($config['db_host'],$config['db_user'],$config['db_pass']) or die();  
mysql_select_db($config['db_name']) or die();  

$news_headlines    mysql_query("SELECT n.*,a.* FROM news AS n LEFT JOIN authors AS a ON a.aid=n.n_author_id ORDER BY n.n_time DESC".(is_numeric($config['headlines']) && $config['headlines']>" LIMIT {$config['headlines']}null));  
$items_output    null;  
if(
mysql_num_rows($news_headlines))  
{  
    while(
$headline mysql_fetch_assoc($news_headlines))  
    {  
        
$link            htmlentities("http://example.com/index.php?act=news&id={$headline['nid']}");  
        
$pubdate        gmdate('r',$headline['n_time']);  
        
$author            $config['show_author_info'] ? "nttt<author>{$headline['a_email']} ({$headline['a_name']})</author>" null;  
        
$description    nl2br($headline['n_body']);  
          
        
$items_output .= <<<EOF  

        
<item>  
            <
title>{$headline['n_title']}</title>  
            <
description>  
                {
$description}  
            </
description>  
            <
link>{$link}</link>  
            <
pubDate>{$pubdate}</pubDate>{$author}  
        </
item>  
EOF;  
    }  
}  

$config['encoding']    = empty($config['encoding']) ? 'ISO-8859-1' $config['encoding'];  
$copyright            = empty($config['copyright']) ? null "ntt<copyright>".str_replace('{year}',date('Y'),$config['copyright'])."</copyright>";  
$pubdate            $config['show_feed_pubdate'] ? "ntt<pubDate>".gmdate('r')."</pubDate>" null;  
$language            = empty($config['language']) ? null "ntt<language>{$config['language']}</language>";  

$output = <<<EOF  
<?xml version="1.0" encoding="{$config['encoding']}?>  
<rss version="2.0">  
    <channel>  
        <title>{$config['feed_title']}</title>  
        <link>{$config['link']}</link>  
        <description>{$config['description']}</description>{$copyright}{$pubdate}{$language}{$items_output}  
    </channel>  
</rss>  

EOF;  

header("Content-type: application/xml; charset={$config['encoding']}");
Splitting it up
We will start by splitting rss.php up into smaller pieces:

PHP Code:
<? 
include "config.php";  

$link mysql_connect($config['db_host'],$config['db_user'],$config['db_pass']) or die();  
mysql_select_db($config['db_name']) or die(); 
?>
In the start we include our configuration file and establish a connection to the database using the information we have from the configuration file. If either the connection or the selection of the database fails the script will terminate and show a blank page to the user. You might want to change that behavior in the actual application that you would use on your site.

Code:
<? 
$news_headlines    = mysql_query("SELECT n.*,a.* FROM news AS n LEFT JOIN authors AS a ON a.aid=n.n_author_id ORDER BY n.n_time DESC".(is_numeric($config['headlines']) && $config['headlines']>0 ? " LIMIT {$config['headlines']}" : null));  
$items_output    = null; 
?>
In this section of the script we select all the news articles and the author information for each of them. If you know SQL most of it should not be too tricky, but at the end we have a little addition, a ternary operator. It says: if $config['headlines'] is numeric and if it is higher than zero then add "LIMIT {$config['headlines']}" else add null which is "nothing". Make sure you understand the ternary operator as it will be used quite a lot of times in this script.

Example ternary operator (pseudo-code):

Code:
<? 
condition ? if_true : if_false; 
?>
If condition is true, then return if_true else return if_false. More information about the ternary operator in the PHP manual.

PHP Code:
<? 
if(mysql_num_rows($news_headlines))  
{  
    while(
$headline mysql_fetch_assoc($news_headlines))  
    {  
        
$link            htmlentities("http://example.com/index.php?act=news&id={$headline['nid']}");  
        
$pubdate        gmdate('r',$headline['n_time']);  
        
$author            $config['show_author_info'] ? "nttt<author>{$headline['a_email']} ({$headline['a_name']})</author>" null;  
        
$description    nl2br($headline['n_body']);  
          
        
$items_output .= <<<EOF  

        
<item>  
            <
title>{$headline['n_title']}</title>  
            <
description>  
                {
$description}  
            </
description>  
            <
link>{$link}</link>  
            <
pubDate>{$pubdate}</pubDate>{$author}  
        </
item>  
EOF;  
    } 
?>
This next bit of code is the bit of code that deals with the news headlines. First it checks if there is any rows returned, if there is then fetch them in our while loop. As you see we use the ternary operator again and we use gmdate to generate a date in GMT from out timestamp (stored in the database) and we convert any line breaks to HTML linebreaks. Finally we append some stuff to $items_output.

PHP Code:
$config['encoding']    = empty($config['encoding']) ? 'ISO-8859-1' $config['encoding'];  
$copyright            = empty($config['copyright']) ? null "ntt<copyright>".str_replace('{year}',date('Y'),$config['copyright'])."</copyright>";  
$pubdate            $config['show_feed_pubdate'] ? "ntt<pubDate>".gmdate('r')."</pubDate>" null;  
$language            = empty($config['language']) ? null "ntt<language>{$config['language']}</language>"
I do not think this bit of code neads any explanation as it is basicly done in the same ways as other things in the script.

PHP Code:
<? 
$output 
= <<<EOF  
<?xml version="1.0" encoding="{$config['encoding']}?>  
<rss version="2.0">  
    <channel>  
        <title>{$config['feed_title']}</title>  
        <link>{$config['link']}</link>  
        <description>{$config['description']}</description>{$copyright}{$pubdate}{$language}{$items_output}  
    </channel>  
</rss>  

EOF;  

header("Content-type: application/xml; charset={$config['encoding']}");  
echo $output;  
?>
This last bit of code assigns an output, sends a header that tells the browser that it is an XML file and sets the output charset/encoding to what is defined in the configuration file.

I am not going to explain the configuration elements as I think they are self-explanatory, else just look at the code.

The end
That is the end of my tutorial about dynamic RSS feeds. You will of course have to program it so it fits to your site, but that should not be too hard as I have just showed you how it should be done.

Author by Daniel0