1. Introduction
    1. About Agavi
    2. MVC in Agavi
    3. Overview of Agavi
    4. Overview of Application Execution Flow
    5. A Word About Actions
    6. Application filesystem layout
    7. Overview of application configuration
  2. Setting Up The Initial Application
    1. Installing Agavi
    2. Creating an Agavi Project
    3. Finishing The Setup
    4. Finishing The Basic Setup
    5. Installing a New Copy of Your Application
  3. Adding First Code
    1. Creating A New module
    2. Creating A New Action
    3. Tying Things Together — An Introduction To Routing
    4. Fixing The Bloggie Routing
    5. Accessing Request Parameters and Validation Basics
    6. Handling Validation Errors
  4. Putting The M in MVC
    1. Creating A New Model
    2. Adapting The Actions and Views
    3. Custom Validators
  5. Polishing It Up
    1. Layers and Layouts
    2. Applying Our Layout
    3. What Are Slots?
    4. Adding The Post's Title To The URL
    5. Routing Callbacks
    6. Using Callbacks for the Title in URLs
  6. Connecting to a database
    1. The Database Manager
  7. Handling Output Variants
    1. Output Types
    2. Exception Templates
    3. Generating an RSS Feed
  8. Form Processing
    1. Adding a Post
    2. Editing a Post
    3. The Form Population Filter (FPF)
  9. Creating a User Authentication System
  10. Adding To The Master Template

Generating an RSS Feed

We'll be using Zend_Feed to generate the RSS feed, so we need the relevant parts of the Zend Framework installed. Just drop the pieces you need in libs/Zend and have an include path point at libs/. This is best done by adding a line to app/config.php:

ini_set('include_path', dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'libs' . PATH_SEPARATOR . ini_get('include_path'));

First, we need to define a suitable output type for the RSS feed. We don't need a renderer or a layout as we'll use a generator for the feed. We should provide a proper Content-Type header as well - we'll be using "text/xml". So our output type definition looks like this:

<output_type name="rss">
  <ae:parameter name="http_headers">
    <ae:parameter name="Content-Type">text/xml; charset=UTF-8</ae:parameter>
  </ae:parameter>
</output_type>

Now we need to add a route that set's the output type. We want any url that ends in ".rss" to be mapped to the "rss" output type. So we place this route at the top of our routing.xml

<route name="ot_rss" pattern=".rss$" cut="true" stop="false" output_type="rss" />

All that's left to do now is implement the appropriate executeRss() method on the views where we'd like to provide an rss feed. Let's start with the index page. All we need to do is provide a good implementation for Posts_IndexSuccessView::executeRss():

public function executeRss(AgaviRequestDataHolder $rd)
{
  $ro = $this->getContext()->getRouting();
  $entries = array();
  
  foreach($this->getAttribute('posts') as $p)
  {
    $entries[] = array(
      'title'       => $p->getTitle(), //required
      'lastUpdate'  => time(), // optional
      'link'        => $ro->gen('posts.post.show', array('post' => $p), array('relative' => false)), //required
      'charset'     => 'UTF-8', // required
      'published'   => time(), //optional
      'description' => $p->getContent(), //optional
      'author'      => $p->getAuthorName(), //optional
      'language'    => 'en', // optional
    );
  }
  
  $data = array(
    'title'       => 'Latest Posts', //required
    'lastUpdate'  => null, // optional
    'link'        => $ro->gen(null, array(), array('relative' => false)), //required
    'charset'     => 'UTF-8', // required
    'published'   => time(), //optional
    'description' => 'The latest posts from the agavi tutorial blog application', //optional
    'author'      => null, //optional
    'language'    => 'en', // optional
    'entries'     => $entries
  );

   
  require 'Zend/Feed.php';
  $feed = Zend_Feed::importArray($data, 'rss');
  
  return $feed->saveXml();
}

I won't go into the details of Zend_Feed but all we did was construct the proper data array and have the library construct the feed to us. The Zend_Feed_Element::saveXml() returns the generated XML which we use as return value for the executeRss() method. As there is no renderer involved the return value gets sent straight to the client. We didn't use the Zend_Feed_Abstract::send() method as sending headers and content directly would cause major problems with the framework, especially with the caching mechanism.

Note how we did not use the post's posted date in the feed - Zend_Feed expects a timestamp at this place and we're storing a string. We'll get to that when we're handling the calendar library and the translation subsystem.