It's sometimes necessary for a controller to use a different site layout (e.g. a admin controllers will use a different site template than the public facing site). What is the best way to handle this?
One option is to use a different front controller for each, but this seems messy, essentially you're only changing the overall view used.
In CakePHP (for example) you do $this->layout = 'Admin'; or similar in the controller. This makes sense but is this really anything the controller should really be concerned with?
Sometimes you need to specify a different site template based on logic (user type or anything really) Should this go in the controller? I'd say this is messy, especially if this logic is needed in more than one place.
My current solution is to treat 'config' (the overall application config) object as a model and allow it to be modified from the controller (or other models). The front controller already reads from this to get the default site template so the only real change is making this value writeable by models/controllers but having writeable configuration seems dangerous at best.
How does everyone else handle this?
I can call $this->layout( 'newtemplate.phtml' ); in my view, which I usually do. However, I could also call $this->view->layout( 'newtemplate.phtml' ); from the controller to achieve the same result: it depends on the situation which one is best. I like the view to do a lot for itself, so other controllers can use the same view without repeating lots of code, but if it's the view that is repetitive, you should consider putting it in the controller (or better yet, a View Helper). As always, YMMV.
Well putting it in the view (or view helper) seems wrong to me. You're tying the view in to a specific layout meaning I can't reuse a view for both the admin area and normal site (or ajax requests, etc)
All approaches mentioned so far are valid. However, in some cases not really useful:
Let me take a step back and ask: What scenarios may we need to change the layout?
Admin area as mentioned.. This will use specific controllers so putting it in the controller makes sense
"Printable version of this page". Tough one, for this I currently use a specific controller which sets the layout then initialises the desired controller and passes the request along. e.g. /user/list/2 becomes /print/user/list/2 so everything is wrapped through the print controller. Kinda messy but printable pages need their own URI and application specific logic certainly does not belong in a generic front controller. While not always necessary (it should be possible with stylesheets alone, sometimes it's not)
Ajax requests There's no reason an ajax request shouldn't be able to call the same controller and just bring back the view html from the controller without the layout. In this case it certainly belongs in the front controller, checking the request type and selecting the layout. This logic certainly shouldn't be in the controller.
Site-wide layout selection logic. On some sites you may have different layouts depending on certain factors. I'll use "Account Customer"/"Normal Customer" as a simple example. Clearly this needs to apply to all controllers.
When outputting to a different data type (image, pdf, etc). I'd generally say this belongs in the controller or view.
My biggest issue, is there are times when it's needed in multiple places with no clear or consistent order of precedence:
-If I make an ajax request in the admin area, it needs to use the ajax layout: Front controller has precedence
-if I'm an "Account customer" and request an image, it still needs to display as an image: Controller has precedence
I have a method called setMasterTemplate in the front end controller that makes it possible for any module to change the layout. The default (public facing) layout path is read in from an XML file and may be changed as needed by passing the new path during execution of every module for the request. A perfect example of needing to change the layout is for different types of request such as images, videos, files stored outside the site root. In that case my master module (begins module execution) changes the layout so that those items can be served up appropriately using the same entry point.
I don't think modifying the config is the right answer. I look at the config as a holy entity of the sorts which is either read or written to. If your not writing something to config to update a value then I don't think you should be changing it. Either read, write or copy the data to a new variable but try to avoid temporarily changing the config per a request. That just seems like grounds for disaster for someone unfamiliar with the system.
I think this is fine, I am doing it this way and I like it so far.. Sometimes I try to automate too much (in my opinion) and I feel like I should just rename the controller to the automater, haha.
I do the following..
// Renders: className/default.tpl
// Renders: className/page.tpl
Before, I had $this->Render automated to run if it wasn't called in the Controller -- but I decided to turn it off so that in the future if I just want to pass some PHP without a view (ie: ajax), I don't need to render a template.
public function Edit($intID)
$intID = (int) $intID;
$this->Assign('title', 'Edit My Listing');
I don't see anything wrong with this in your controller:
$this->layout = 'Admin';