View in MVC, what is a layout and how to create on

2019-02-21 03:00发布

问题:

I dont understand what the layout is, in the view. I asked a question previously on the subject of templating in PHP, but I still dont quite understand. I assume that you create a general layout for the site and then include each specific view within that layout.... I would like to know how to go about doing this. Also, are should the templates be made using just html, because I also looked at these things called helpers.... I'm just confused on the View part of the MVC, and the actual templates and how they're made. I learn best with examples, If you guys have any.

Also, a more important question, lets say I had a form that a user saw only if he was logged in, would I control that in the view, or in the controller?

So Would i do

in the controller

include 'header';
if(isset($_SESSION['userID'])){
    include 'form';
}
include 'footer';

or

in the template

<html>
<?php if(isset($_SESSION['user_id'])): ?>
  <form>....</form>
<?php endif;?>
</html>

EDIT

So, is there an include statement from within the layout to see the specific view template? how so?

回答1:

I hesitate to answer this question only because of the religious fervor that surrounds it.

To get a really good understanding of the issues behind the general concepts see This Wiki Discussion Page This is the discussion page around the wiki MVC article.

Here is the rule of thumb I like to follow (BTW I use CodeIgniter and it kind of sounds like you are too):

The "view" should have virtually no logic. It should only be HTML (in the web world) with peppered PHP that simply echos variables. In your example you would break out the form into its own view and the controller would determine if was loaded or not.

I like to look at it this way: The view should have no concept of where the data comes from or where it is going. The model should be view agnostic. The controller meshes data from the model and provides it to the view - and it takes input from the view and filters it to the model.

Here is a quick and dirty (untested - but it should get the point across) example:

Theapp.php (The App controller)

class Theapp extends Controller
{
   var $_authenticated;
   var $_user;
   var $_menu; // array of menus

   function __construct()
   {
      session_start();
      if (isset($_SESSION['authenticated']) && $_SESSION['authenticated'])
      {
           $this->_authenticated = $_SESSION['authenticated'];  // or some such thing
           $this->_user = $_SESSION['user'];
      }
      $this->_menu = array("Logout", "Help", "More");
      parent::__construct();
      $this->loadView("welcome"); // loads primary welcome view - but not necessarily a complete "html" page
   }


   function index()
   { 
      if (!$this->_authenticated) 
         $this->loadView("loginform");
      else
      {
         $viewData['menu'] = $this->_menu;
         $viewData['user'] = $this->_user;
         $this->loadView("menu", $viewData);
      }
   }


   function login()
   {
      /* code to authenticate user */
   }

   function Logout() { /* code to process Logout menu selection */ }
   function Help() { /* code to process Help menu selection */ }
   function More() { /* code to process More menu selection */ }
}

welcome.php

<h1> Welcome to this quick and dirty app!</h1>
All sorts of good HTML, javascript, etc would be put in here!

loginform.php

<form action"/Theapp/login" method="post">
   User: <input id='user' name='user'>
   Pass: <input id='pass' name='pass' type='password'>
   <input type='submit'>
</form>

menu.php

Hi <?= $user ?>!<br>
Here's your menu<br>
<? foreach ($menu as $option) { ?>
<div class='menuOption'><a href='/Theapp/<?=$option?>'><?=$option?></a></div>
<? } ?>

Hope this helps.



回答2:

a layout is whatever you have around your main content area. Usually on a normal website it would be any sidebar,header,footer. Most of MVC framework provide the layout to avoid to repeat those parts in all views.

You can imagine if like you have two view cascaded

  1. you actual view is rendered, this content is saved
  2. the layout view (all the items around the content) are rendered and your content is included in that output

for your login question actually your would have to do both on the controller and the view

$this->view->isLogged = isset($_SESSION['userID']);

in the view

<?php if($isLogged): ?>
  <form>....</form>
<?php endif;?>


回答3:

If your not using a framework, then a simple way to have a layout and a view can be like so:

<?php
function layout($layout_params) {
  extract($layout_params);

  # Remember: $layout_content must be echoed for the view to be seen.
  ob_start();
  include "layout_page.php";
  $html = ob_get_contents();
  ob_end_clean();

  return $html;
} 

function view($view_params) {
  extract($view_params);

  ob_start();
  include "home_page.php";
  $html = ob_get_contents();
  ob_end_clean();

  return $html;
}

#
# The variable $parameters is extracted and $params becomes a variable in the view as an array,
# $logged_in is also now avaiable in the view
# 
$parameters = array("params" => array("name" => "joe"), "logged_in" => false);

$view_content = view($parameters);  # => Returns the HTML content for home_page.php

# Now we need the layout content to include the view:
# The layout file will expect a variable called $layout_content to be the html view.
# So we need to set $layout_content to be $view_content
$parameters["layout_content"] = $view_content;

# We no longer need $view_content so we can unset the variable
unset($view_content);

# When $paramters is extracted it will have $layout_content as a variable:
$layout_content = layout_view($paramters); # => Returns the HTML content for the layout_page.php

# Now send the results to the browser
echo $layout_content;

?>