How to handle templates for MVC websites?

I have this as PHP, but only because I will use PHP code to show my problem.

So, I have this code for the controller:

switch ($page) { case "home": require "views/home.php"; break; case "search": require "views/search.php"; break; } 

Obviously there are more pages, but this should illustrate my problem. There is a common header, navigation, and footer for both of these pages (and for all pages on the site, for that matter). Should I use multiple query operators? My first guess:

 switch ($page) { case "home": require "templates/header.php"; require "templates/navigation.php"; require "views/home.php"; require "templates/footer.php"; break; case "search": require "templates/header.php"; require "templates/navigation.php"; require "views/search.php"; require "templates/footer.php"; break; } 

Somehow, my gut tells me that this is not true.

+6
php model-view-controller view
source share
8 answers

The controller should simply configure the data for presentation and choose which view to display. The view should be responsible for the layout of the page, including shared pages. I like your first sample in a second.

+5
source share

Yes, you must have separation of header, footer, etc.

For the specific example that you are showing, will this not work better?

  require "templates/header.php"; require "templates/navigation.php"; require "views/$page.php"; require "templates/footer.php"; 

(where $ page is "home", "search", etc.)

+1
source share

Here is a simplified version of how I make templates with my current project, if used:

 class Template { var $pagename = 'index'; function __construct() { $this->pagename = basename($_SERVER['SCRIPT_NAME'], '.php'); register_shutdown_function(array($this, 'do_output')); } function do_output() { $this->header(); $this->display($this->pagename); $this->footer(); } function __call($template, array $params) { call_user_func(array($this, 'display'), $template, params); } function display($template, array $params = null) { include "templates/$template.php"; } } 

The idea is that you can write "include" Template.inc ", a new template;" and it organizes do_output () to automatically run at the end of the script. There are a few things left, like the method used to pass variables to the template.

You mentioned that you are not using PHP, and there are several PHP-isms there: register_shutdown_function () ensures that the templates will be called before the object destructors, but after the main script and calls in $ this → header () / footer () - calls to the magic functions that simply display ("header") and display ("footer"), they are intended to be overridden.

Of course, there is nothing wrong with using a switch, as in the example you posted, but you don't need headers and footers inside each case statement. Something like this will do the same:

 require "templates/header.php"; require "templates/navigation.php"; switch ($page) { case "home": require "views/home.php"; break; case "search": require "views/search.php"; break; } require "templates/footer.php"; 

... or you can replace the switch () with something based on the file name, as I used above, if it works to customize your pages. The switch is the safest way if you plan to do this through the URL parameters.

0
source share

You repeat the code. This is almost never a good idea. To get closer to your original example, something like this would be preferable:

 require "templates/header.php"; require "templates/navigation.php"; switch ($page) { case "home": require "views/home.php"; break; case "search": require "views/search.php"; break; } require "templates/footer.php"; 

It is hard to give more advice without knowing more about your architectural approach. For example, it would be desirable to have this part of the controller that simply prepares the output in a very central location and trigger output buffering before including presentation templates. That way, you can save the output in a variable that you might want to process further before returning its contents to the HTTP response.

0
source share

I agree with tvanfosson and want to explain why and how it relates to MVC.

The problem with your second example is that the controller is exposed to how the view is created. In the strict sense, the controller controls the inputs for the presentation and passes them to it, and nothing more.

A practical way to think about this is that the presentation shifts depending on the requirements of the application or the inputs themselves. For example, if the generated view refers to a JavaScript popup, it can (and probably will) use a different set of headers, footers, CSS, meta, etc. In the second example, everything that is available to the controller, First, this is a view that knows how to generate a view - this is exactly the point.

To take my example further, imagine that the JavaScript popup has been redesigned to be a full pageview, or refactored for AJAX (or the popup / page / AJAX question is determined by input, for example, a hidden element in a field). Now you are breaking the controller because the view has changed. It is not that you violated MVC, but you should not have worried about it in the first place.

0
source share

If all your file names match your view / page request, as shown in the example, you just need one line and a switch :

 require "templates/header.php"; require "templates/navigation.php"; require 'views/' . $page . '.php'; // <-- one-liner require "templates/footer.php"; 
0
source share

Is there any specific reason why you are not using an MVC environment such as Symfony or CakePHP ?

I know that this does not answer the question directly, but it can be useful.

-2
source share

If you use direct PHP pages as your templates, you can essentially set a global / session variable to hold the page you want. You will have a “master template” php page that includes header and footer elements and then calls include for the $ page. Something like this in the controller:

 $_SESSION['page'] = sanitize_input($_GET['page']); require "templates/main.php"; 

and then in the main.php template file:

 require "templates/header.php"; require "templates/navigation.php"; require "views/{$_SESSION['page']}.php"; require "templates/footer.php"; 
-2
source share

All Articles