Porto

Introduction To eZ Components part 3

Introduction To eZ Components part 3

eZ Components From go to WHOA!Part 3

Create An RSS Feed With eZ Components

By Kevin Waterson

Contents

  1. Abstract
  2. White Board
  3. The Database
  4. Query the Database
  5. The Feed
  6. Cron
  7. Putting it all together

Abstract

In part one and part two of this series, we focused on creating simple pages and how to deal with templates a forms. In this chapter we explore the world of RSS feeds. You have most likely seen an RSS feed on many blogs etc that pollute the net. These feeds offer an excellent method to keep up to date with what is happening on a site. Here we will explore the creation of a feed based on information stored in a MySQL database, and how to read a feed.

To understand the code flow through-out this tutorial it is assumed you have read part one and part two of this series to get you started.

Once again, this tutorial will be using several eZ components from the component library. We have already seen in Parts One and Two, the use of several components. Here we will introduce the Database component and the Feed component. By using these together, we will create an RSS2 feed and a feed reader.

It is beyond the scope of this document to show how PHP and MySQL work together. If you do not already know how to use MySQL with PHP it is highly recommended you familiarise yourself with the tutorial Introduction to PHP and MySQL.

White Board

Consideration is given here to the database that stores the feed information and to the feed component itself. What type of feed will be created and how will this be available to end users.

The feed requires the following

  • Connect to Database
  • Retrieve data from Database
  • Format data to feed XML
  • Create download method for users

With these tasks in mind, we will see how easy the ezComponents library makes this job using very little code.

The Database

Like most web based applications of today and sites that contain dynamic documents, a database is employed to store the information and related information. The PHPRO site is no different and uses a central "knowledge base" to store the PHP articles, tutorials and examples you see here on the site. To connect to the database we use the Database component. The Database component allows for simple creation of a database object and a simple Object Oriented interface to our queries. The database component even has a robust abstraction layer, but more on that at another time.

As with all eZ Component scripts, we begin with the inclusion of the base class that permits access to the eZ magic.


<?php

/*** path to the base file ***/
 
$ezBase 'ezcomponents/Base/src/base.php';

 if(!
file_exists($ezBase))
 {
    echo 
'Could not find base file in '.$ezBase;
 }
 else
 {
    
/*** include the base file ***/
    
include $ezBase;

    
/*** Autoload the ezcomponent classes. ***/
    
function __autoload$className )
    {
            
ezcBase::autoload$className );
    }
 }

?>

The above snippet of code should look familiar to those who have read the first two tutorials and you may have guessed to put this part of the script into its own file and include it. Now we move into the connection to the database. As the database component uses PDO as its base, we can connect to the database in the same easy fashion using a DSN.


<?php

 
/*** connect to database ***/
 
$db ezcDbFactory::create'mysql://username:password@localhost/phpro' );

?>

Above we have created a variable that contains an instance of the database object which we can now use directly in our script. Should we wish to execute more queries we could set the instance using ezcDbInstance::set() and then anywhere else we chose to query the database, the instance could be retrieved with ezcDbInstance::get(). The code would look a little like this.


<?php

 
/*** connect to database ***/
 
$db ezcDbFactory::create'mysql://username:password@localhost/phpro' );

 
/*** set the database instance ***/
 
ezcDbInstance::set$db );

 
/*** get the database instance ***/
 
$db ezcDbInstance::get();

?>

Query the Database

Running a database in eZ Components is quite simple. First we call our instance and then run the query method and assign it to a variable $row containing the result set that we can later iterate over.


<?php

 
/*** run a query ***/
 
$rows $db->query"SELECT
                articleid,
                article_name,
                article_description,
                article_date
                      FROM
                phpro_articles
                      WHERE
                article_category='articles'
                      ORDER BY
                article_date
                      DESC
                      LIMIT 20" 
);
?>

The code above provides no real surprises. The use of ezcDbInstance::get() calls the database connection and assigns it to the variable $db. The query() method is used to run the query. Some small effort has been made to format the SQL statement so it is readable. Of course, we did not need to assign the database instance to a variable and could have chained the call to the query method as follows.

$rows = ezcDbInstance::get()->query(...);

This is quite valid but for the sake of readability in this tutorial the variable has been assigned. The variable $rows now contains an array of arrays. Each of the arrays contained within carries a result set which can now be iterated over. Because the eZ Components database component builds on top of PDO, SPL iterators are used internally making traversal of result sets very memory efficient.

When we iterate over the result set, we want to be able to assign the values within to the feed. To do this, we need to begin the feed object.

The Feed

Like all other eZ Components, to start the feed we begin by creating a new feed object. The syntax is the same as with all other like this:

<?php

 
/*** create a new feed object ***/
 
$feed = new ezcFeed'rss2' );

?>

So, no surprises in the above, but note that the type of feed has been specified as rss2. This could have been rss1 or atom but to begin with, we will create just a single feed type and progress to other feed types in a later article

The RSS2 specification shows there are three required elements for a feed.

title
The name of the channel. It's how people refer to your service. If you have an HTML website that contains the same information as your RSS file, the title of your channel should be the same as the title of your website.
link
The URL to the HTML website corresponding to the channel
description
Phrase or sentence describing the channel.

There is a quite an array of optional elements, but first the required elements need to be addressed. The eZ Components system makes this quite simple for us. Having already created the feed object above, it is now a simple matter of assigning values to the feed.

<?php

        
/*** feed title ***/
        
$feed->title 'PHPRO Articles';

    
/*** the feed description ***/
        
$feed->description 'PHP Articles from PHPRO';

    
/*** the feed link ***/
        
$link $feed->add'link' );
        
/*** set the link ***/
        
$link->set'http://www.phpro.org/feed.php' );
?>

The comments above are self explanatory. The feed title, feed description are set, and the feed link is added, and then set. Adding further link items to the feed is now just a matter of looping through the database result set, and setting more.

<?php
 
foreach( $rows as $row )
 {
    
$article_link ='http://www.phpro.org/articles/'.str_replace(' ''-'$row['article_name']).'.html';
    
$item $feed->add'item' );
    
$item->title $row['article_name'];
    
$item->description $row['article_description'];
    
$link $item->add'link' );
    
$link->set$article_link );
 }
?>

Finally, the feed needs to be generated and written to a file. This is done with the feed generate() method. At this point we could simply echo the generated xml from the feed, but to save on resources, the output will be written to disk and the script run from cron. You can decide yourself the frequency of the cron script to generate the feed, but if you consider a high volume site, the extra load on the database can be reduced to a single hit per hour rather than one hundred thousand.


<?php

    
/*** generaate the feed xml ***/
    
$xml $feed->generate();

    
/*** check the file is writable ***/
    
if ( is_writable$feed ) )
    {
        
/*** write the feed ***/
        
file_put_contents$feed$xml );
    }

?>

And now you have a fully functional RSS2 feed. It is left to the user as an exercise to discover more information that can be added to the feed. But this simple method will provide a feed for your database results.

Cron

As this script is designed to run from cron, we have included here is a few cheats to set up your cronjob. We will assume the script is called article_feed.php for use in cron. Using crontab -e you can enter following:

Every 15 minutes
0,15,30,45 * * * * /path/to/articles_feed.php
Every Hour at 5 past
5 * * * * /path/to/articles_feed.php
Once a day
10 3 * * * /path/to/articles_feed.php

Putting It All Together

As is the tradition at PHPRO.ORG we supply the completed script for your enjoyment.


<?php

/*** path to the base file ***/
 
$ezBase '/www/ezcomponents/Base/src/base.php';

 if(!
file_exists($ezBase))
 {
    echo 
'Could not find base file in '.$ezBase;
 }
 else
 {
    
/*** include the base file ***/
    
include $ezBase;

    
/*** Autoload the ezcomponent classes. ***/
    
function __autoload$className )
    {
        
ezcBase::autoload$className );
    }
    try
    {
        
/*** connect to database ***/
        
$db ezcDbFactory::create'mysql://username:password@localhost/phpro' );

        
/*** set the database instance ***/
        
ezcDbInstance::set$db );
    
        
/*** get the database instance ***/
        
$db ezcDbInstance::get();

        
/*** run a query ***/
        
$rows $db->query"SELECT
                    article_id,
                    article_name,
                    article_blurb,
                    article_date
                FROM
                    phpro_articles 
                WHERE
                    article_category='articles'
                ORDER BY
                    article_date DESC
                LIMIT 20" 
);

        
/*** create a new feed object ***/
        
$feed = new ezcFeed'rss2' );

        
/*** feed title ***/
        
$feed->title 'PHPRO Articles';
        
$feed->description 'PHP Articles from PHPRO';

        
/*** ERROR ON THIS LINE ***/
        
$link $feed->add'link' );
        
$link->set'http://www.phpro.org/feed.php' );

        foreach( 
$rows as $row )
        {
            
$article_link ='http://www.phpro.org/articles/'.str_replace(' ''-'$row['article_name']).'.html';
            
$item $feed->add'item' );
            
$item->title $row['article_name'];
            
$item->description $row['article_blurb'];
            
$link $item->add'link' );
            
$link->set$article_link );
        }
    
        
/*** generaate the feed xml ***/
        
$xml $feed->generate();

        
/*** the feed file ***/
        
$feed 'articles_feed.php';

        
/*** write the xml file ***/
        
if ( is_writable$feed ) )
        {
            
file_put_contents$feed$xml );
        }

    }
    catch( 
Exception $e )
    {
        echo 
$e->getMessage();
    }
 }
?>