Creating A New Model
We'll use the Agavi build script to generate the two models we need. As they belong to the posts handling part of our application, we'll create them in the in the Posts module:
bloggie$ dev/bin/agavi model-create
Module name: Posts
Model name: Post
bloggie$
This will create the Posts_PostModel in the directory app/modules/Posts/models/. The class will be empty for now, we'll add code to it in a second. First, let's repeat the same steps for the PostManager model.
bloggie$ dev/bin/agavi model-create
Module name: Posts
Model name: PostManager
bloggie$
Now you should have two files in app/modules/Posts/models/, one named PostModel.class.php, one named PostManagerModel.class.php containing the empty classes Posts_PostModel and Posts_PostManagerModel. Note how both classnames are prefixed with the module's name and that they both end in "Model". This convention is used through out agavi. While it is possible to reference models that have different naming schemes we recommend sticking to this convention.
Both models extend the BlogPostsBaseModel class that was created when we created the module.
Instantiating Models
Now that we created the model classes, we need a way to create instances. We could go the long route with including the class file, creating a new instance with new Posts_PostModel and then calling the required initialize() method. However, there is an easier way. Any object with access to the AgaviContext (which is pretty much every object in the framework) can just call $ctx->getModel(<modelname>, <modulename>, <optional parameters>) to create a fully initialized instance of the given model. The context will then locate the proper class file, load it if required, and return an initialized instance of the requested model.
Fleshing Out The Models
Let's add a bit of functionality to the models. The Post model currently is just a container for the data a Post can have, so we'll primarily add the attributes and getters and setters for those attributes and throw in two methods to create a post from an array of values and reverse. Your final Posts_PostModel [app/modules/Posts/models/PostModel.class.php] should look like that (the comments are left out to keep it short):
<?php
class Posts_PostModel extends BlogPostsBaseModel
{
private $id;
private $title;
private $posted;
private $categoryName;
private $authorName;
private $content;
public function __construct(array $data = null)
{
if(!empty($data))
{
$this->fromArray($data);
}
}
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getTitle()
{
return $this->title;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getPosted()
{
return $this->posted;
}
public function setPosted($posted)
{
$this->posted = $posted;
}
public function getCategoryName()
{
return $this->categoryName;
}
public function setCategoryName($name)
{
$this->categoryName = $name;
}
public function getAuthorName()
{
return $this->authorName;
}
public function setAuthorName($name)
{
$this->authorName = $name;
}
public function getContent()
{
return $this->content;
}
public function setContent($content)
{
$this->content = $content;
}
public function fromArray(array $data)
{
$this->setId($data['id']);
$this->setTitle($data['title']);
$this->setPosted($data['posted']);
$this->setCategoryName($data['category_name']);
$this->setAuthorName($data['author_name']);
$this->setContent($data['content']);
}
public function toArray()
{
$data = array();
$data['id'] = $this->getId();
$data['title'] = $this->getTitle();
$data['posted'] = $this->getPosted();
$data['category_name'] = $this->getCategoryName();
$data['author_name'] = $this->getAuthorName();
$data['content'] = $this->getContent();
return $data;
}
}
?>
The Posts_PostManageModel [app/modules/Posts/models/PostManager.class.php] is responsible for all storage and retrieval operations. We currently need two operations: Retrieve a single Post and retrieve the latest posts for the front page. As we now do have a model encapsulating all the data retrieval we can move our mock-data into that model. The end result should look like this:
<?php
class Posts_PostManagerModel extends BlogPostsBaseModel
{
private $posts = array(
1 => array(
'id' => 1,
'title' => 'First post',
'posted' => '2008-07-14 00:01:07',
'category_name' => 'No category',
'author_name' => 'Admin',
'content' => '<p>Terrific! This is our first post!</p><p>This is just a first post. It has no actual contents. If you are reading this, things must be working.</p>',
),
2 => array(
'id' => 2,
'title' => 'Second post',
'posted' => '2008-07-14 00:01:07',
'category_name' => 'Agavi',
'author_name' => 'Admin',
'content' => '<p>It looks like our blog application is working, yay!</p>',
)
);
public function retrieveById($id)
{
if (isset($this->posts[$id]))
{
return $this->getContext()->getModel('Post', 'Posts', array($this->posts[$id]));
}
return null;
}
public function retrieveLatest($limit = 5)
{
$cnt = 0;
reset($this->posts);
$posts = array();
foreach($this->posts as $post) {
$posts[] = $this->getContext()->getModel('Post', 'Posts', array($post));
$cnt++;
if($cnt >= $limit) {
break;
}
}
return $posts;
}
}
?>

