Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Explanation of ViewModels
  • Has anyone got a full tutorial for how to use ViewModels? I have read the documentation but because the examples are incomplete I cannot figure out how to make them work. Also if anyone has solid examples of when ViewModels should be used it would be much appreciated. I have seen the standard paragraph that everyone has copied and pasted on their websites but I still don't understand it. If I have a page that simply lists clients, and I put the logic of getting the clients into the ViewModel, what does the controller do? This may be unrelated but this is what got me trying to read into ViewModels. I simply want to set the title of the page, but I don't feel like the controller is the right place to do it. The title is dependent on the view, not on the control logic. Another way to think of it is if I have the controller returning HTML or JSON depending on the request type, then I would only need to set the page title if the request is HTML, not JSON. So putting it into the controller doesn't make sense when the item is view specific. Another reason is we often customise views for different clients, so again putting that logic into the controller would create a huge mess. Instead we just have different views for the different clients and customise it there. What I don't understand is then how to pass the title from the view back up to the layout? If it was CakePhp in the template I would simply do something like:
    $this->pageTitle = 'My Custom Page Title';
    

    And then in the layout I would have:
    <title><?=$this->pageTitle?></title>
    

    Similarly if I wanted different views to have different sidebars, I could put:
    $this->sidebar = 'standard';
    

    into the template, and then read that value out in the layout to render the correct sidebar. I hope I am making sense. Thanks.
  • In Fuel, from a controller point of view, you use a Viewmodel exactly the same way as a view. And for exactly the kind of reasons you mention.
    // load a view in your controller
    $view = \View::forge('this/that');
    
    // load a viewmodel instead
    $view = \Viewmodel::forge('this/that');
    
    This requires a viewmodel class called View_This_That, in a file called that.php, in the classes/view/this folder. By default it loads the same view as in the first example, views/this/that.php. By default, the method called view() is called in your viewmodel, that should contain the logic to prepare the variables for your view. Difference with Cake is that in the view, they're just variables, not accessed via $this. So $this->title in the Viewmodel method becomes $title in your view. You pass data from your controller to a Viewmodel the same way as with a standard view:
    $view = \Viewmodel::forge('this/that');
    $view->set('var', 'value');
    

    For both Views and Viewmodels, Fuel uses lazy rendering. The view is only rendered (the method called in case of a viewmodel, the view loaded and interpreted, and the result returned) when the object is cast to string, or when you call the render() method.
  • Great, thanks for that explanation. Do you have any ideas on how to achieve the custom views for different clients? Again to reference Cake, I simply insert a new path into the viewPaths so the renderer looks for a custom version first, if it can't find that it reverts to the default one. This also means that because the choice of sidebar (for example) is defined in the view, the different themes can display different content. From what you are saying it sounds like I need to somehow load a different ViewModel for different clients? And what's the difference between View::factory() and View::forge() ?
  • Are the same thing ...
    View::factory() is deprecated in 1.1 dev ... use View::forge()
  • The Viewmodel's view file (which by default has the same name) can be altered using the method set_view() in < 1.1, set_template() in older versions. You can use that inside your viewmodel, to load a different view. Views in Fuel don't have a fallback option, an exception is thrown when the view file does not exist. It might be an interesting feature to be able to pass an array of views to forge(), and loop through them before throwing an exception.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion