ViewModels
ViewModels are optional. If you don't need them, you can use Views.
What is a ViewModel?
A ViewModel is a class that contains the logic that is needed to generate your views. When the controller is done with your user input and is done with whatever actions it needed to take, it turns execution over to the ViewModel to retrieve whatever data is needed for the view. A ViewModel shouldn't do any data manipulation but can contain database calls and any other retrieval or preparation operations needed to generate the View's data.
Creating a ViewModel
First we'll create an empty ViewModel in app/classes/view/index.php
:
class View_Index extends ViewModel {}
Then you create the view to which this belongs in app/views/index.php
:
<h1><?php echo $title; ?></h1>
<ul>
<?php
foreach ($articles as $a)
{
echo '<li>'.$a->title.'</li>';
}
?>
</ul>
On view names
A ViewModel and its view are expected to share the same name. Thus a
ViewModel View_Index
expects the view to be in app/views/index.php
. And underscores
work here the same as with classes, which means that the view for View_Some_Thing
is expected
to be in app/views/some/thing.php
.
This default can be overwritten by setting a non-static $_view
property in your ViewModel with the
View name (without .php suffix).
And last we'll call the ViewModel from the controller:
ViewModel::forge('index');
Now we have everything setup; however, there is still no data passed to the view. It still needs to get a
$title
string and $articles
array passed to it. We do this by adding a view()
method
to the ViewModel which will assign this data:
class View_Index extends ViewModel
{
public function view()
{
$this->title = 'Testing this ViewModel thing';
$this->articles = Model_Articles::find('all');
}
}
And you're done.
Passing functions to views
To pass a View specific function from your ViewModel to your View, you use Closures:
// In the ViewModel
class View_Index extends ViewModel
{
public function view()
{
$this->echo_upper = function($string) { echo strtoupper($string); };
}
}
// Which you can then use in your view:
$echo_upper('this string'); // Outputs: "THIS STRING"