Creating A New module
The index page should contain a list of posts and link to the detail page - don't worry we'll add that one later. For each post, the title and the author is displayed, as well as the date it was posted and the category it was posted in.
Creating A New module
A module is an organizational unit structuring your applications separate areas of concern. A module structures Actions, Views, Models and Templates into a common subdirectory. It can even bring it's own libraries and some configs specific to this module. Handling the Post and displaying them to the user is one area of concern for our blog, so code related to that should be placed in one module.
Creating a new module is a simple task if we use the agavi commandline script. So navigate to the directory where you created your application, invoke agavi module-wizard and answer the questions.
bloggie$ dev/bin/agavi module-wizard
Module name: Posts
Space-separated list of actions to create for Posts: Index
Space-separated list of views to create for Index [Success]:
bloggie$
<!-- default action for "/" -->
<route name="index" pattern="^/$" module="Posts" action="%actions.default_action%" />
Done. The "Index" action in the module "Posts" will now
be the index page. We could now remove the old IndexAction, but just keep
that one for later, we will need it.Adding a template variable
We want to display a list of posts on the index page. For now, we're just concerned about getting the basic html to work, so we just forget about where to get the data from for the time being. We'll just pass a static array of posts to the template. A post will need the following information to be displayed:
- id
- The posts id.
- title
- The posts title.
- author_name
- The authors name.
- posted
- The date the post was created.
- category_name
- The name of the category the post was filed under.
- url
- The url to the posts detail page. We will leave that one empty but include it so that the attributes are complete.
public function executeRead(AgaviRequestDataHolder $rd)
{
$posts = array(
1 => array(
'id' => 1,
'title' => 'First post',
'posted' => '2008-07-14 00:01:07',
'category_name' => 'No category',
'author_name' => 'Admin',
'url' => null
),
2 => array(
'id' => 2,
'title' => 'Second post',
'posted' => '2008-07-14 00:01:07',
'category_name' => 'Agavi',
'author_name' => 'Admin',
'url' => null
)
);
$this->setAttribute('posts', $posts);
return 'Success';
}
$this->setAttribute('_title', 'Index');
As you might already have suspected, it sets a template variable
that we use to control the displayed title. Don't worry if that seems a
little like magic at the moment, we'll show you how that works in a little
while. For now just change the line to read:
$this->setAttribute('_title', 'Latest Posts');
Refresh your browser window, and you should now see the change in the title bar and at the top of the page.
<ul>
<?php foreach ($t['posts'] as $post): ?>
<li>
<a href="<?php echo $post['url']; ?>"><?php echo htmlspecialchars($post['title']); ?></a>
by <?php echo htmlspecialchars($post['author_name']); ?> @ <?php echo $post['posted']; ?>
in <?php echo htmlspecialchars($post['category_name']); ?>
</li>
<?php endforeach; ?>
</ul>
See how we were able to access the attribute 'posts' that we set
earlier on in the action by just using $t['posts']? The
PHP Renderer we're using just makes all the template variables available
as an associative array with their names as key.There's a few things to note about that template. See how all output is wrapped in a htmlspecialchars call? We want valid XHTML, so we can't use any of the characters that are reserved in HTML. We don't want to escape them before storing the post in a database or the like, because maybe we want to generate output that is not html later on and then we'd have to decode them again. Neither do we want to have the htmlspecialchars call in the view as some templating engines do that implicitly. So converting the special chars in the view would make it harder to just swap in a new templating engine. And we don't want to use htmlentities as we're trying to be XML compliant at the same time. If you have any special characters like umlauts, just use UTF-8 as charset and the regular character. It will save you a lot of hassle later on. If htmlspecialchars is too long to type for you, we recommend having a function with a shorter name like h() or hss() that just wraps the call. For the tutorial, we'll stick with the long version.

