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

Adapting The Actions and Views

There are two changes we need to introduce. First we want our actions and views to use the models we created in the last step. Second we should move all data retrieval code to the place where it belongs - in the Action. Let's start with the Post.Show Action.

As our Post.IndexAction should respond to GET - Request, we'll need to adapt executeRead() that contains our data retrieval logic. Using the Posts_PostManagerModel [app/modules/Posts/models/PostManager.class.php] we created in the last step this is very little work:

<?php

class Posts_IndexAction extends BlogPostsBaseAction
{
  /**
   * Serves Read (GET) requests
   * 
   * @param      AgaviRequestDataHolder the incoming request data
   * 
   * @return     mixed <ul>
   *                     <li>A string containing the view name associated
   *                     with this action; or</li>
   *                     <li>An array with two indices: the parent module
   *                     of the view to be executed and the view to be
   *                     executed.</li>
   *                   </ul>
   */
  public function executeRead(AgaviRequestDataHolder $rd)
  {
    $manager = $this->getContext()->getModel('PostManager', 'Posts');
    $this->setAttribute('posts', $manager->retrieveLatest(10));
    
    return 'Success';
  }
  
  /**
   * Returns the default view if the action does not serve the request
   * method used.
   *
   * @return     mixed <ul>
   *                     <li>A string containing the view name associated
   *                     with this action; or</li>
   *                     <li>An array with two indices: the parent module
   *                     of the view to be executed and the view to be
   *                     executed.</li>
   *                   </ul>
   */
  public function getDefaultViewName()
  {
    return 'Success';
  }
}

?>

Now we need to adapt the view accordingly:

<?php

class Posts_IndexSuccessView extends BlogPostsBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd);

    $ro = $this->getContext()->getRouting();
    
    $posts = array();
    
    foreach($this->getAttribute('posts') as $p)
    {
      $post = $p->toArray();
      $post['url'] = $ro->gen('posts.post.show', array('post' => $p->getId()));
      $posts[] = $post;
    }
    
    $this->setAttribute('posts', $posts);
    
    $this->setAttribute('_title', 'Latest Posts');
  }
}

?>

Note how we transform the objects we retrieved from our PostManager to arrays. While it may seem easier to pass objects to the template it removes a lot of flexibilty. Some template engines don't handle objects gracefully. There is little added overhead and little code we had to add for that as we need to add some information anyways - in our case the url to the post detail page. We could have added the url in the PostModels toArray() method but that would be bad practice - the url is probably only required in this specific context and would be useless clutter in all other occasions.

Let's just go over our Post.Show action and adapt that, using our models it will be a breeze:

class Posts_Post_ShowAction extends BlogPostsBaseAction
{

  public function executeRead(AgaviRequestDataHolder $rd)
  {

    $manager = $this->getContext()->getModel('PostManager', 'Posts');
    $this->setAttribute('post', $manager->retrieveById($rd->getParameter('post')));

    return 'Success';
  }

  public function getDefaultViewName()
  {
    return 'Success';
  }
}

class Posts_Post_ShowSuccessView extends BlogPostsBaseView
{
  public function executeHtml(AgaviRequestDataHolder $rd)
  {
    $this->setupHtml($rd);
    
    $post = $this->getAttribute('post')->toArray();
    $this->setAttribute('post', $post);
    
    $this->setAttribute('_title', $post['title']);
  }
}

And that's it. Now our actions and views are completely decoupled from the data retrieval, they don't care about whether data is loaded from a flatfile, retrieved from a database, from a webserver or just faked with a static array like we do. You can bet that this will come in handy at some later point.