如何处理MVC网站的模板?

时间:2008-12-01 01:06:45

标签: php model-view-controller view

我将此标记为PHP,但仅仅是因为我将使用PHP代码来显示我的问题。

所以我为控制器提供了这样的代码:

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

显然会有更多页面,但这应该说明我的问题。这两个页面都有一个共同的页眉,导航和页脚(对于网站上的所有页面)。我应该使用多个require语句吗?我的第一个猜测是:

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;
}

不知怎的,我的直觉告诉我这不正确。

7 个答案:

答案 0 :(得分:5)

控制器应该只为视图设置数据并选择要显示的视图。视图应负责页面的布局,包括共享页面。我喜欢你的第一个样本。

答案 1 :(得分:1)

是的,你应该将页眉,页脚等分开。

对于您展示的特定示例,这不会更好吗?

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

($ page是'home','search'等)

答案 2 :(得分:0)

以下是我如何使用当前项目进行模板的简化版本,如果它有用的话:

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";
    }
}

它背后的想法是你可以写“包含'Template.inc';新模板;”它安排do_output()自动在脚本结束时运行。除了用于将变量传递给模板的方法之外,还有一些遗漏的东西。

你提到你没有使用PHP,并且里面有一些PHP主题:register_shutdown_function()确保模板在对象析构函数之前调用但在主脚本之后调用,并调用$ this-&gt ; header()/ footer()是魔术函数调用,只是显示('header')和display('footer'),它们意味着被覆盖。

当然,使用像您发布的示例一样的开关没有任何问题,但您不需要在每个case语句中使用页眉/页脚。这样的事情会做同样的事情:

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";

...或者您可以根据我上面使用的文件名替换switch(),如果它适用于您的页面设置方式。如果您计划通过URL参数进行此操作,则交换机是最安全的方式。

答案 3 :(得分:0)

你正在重复代码。这绝不是一个好主意。为了接近你最初的例子,这样的事情肯定会更好:

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";

如果不了解更多有关您的架构方法,很难提供更多建议。例如,建议将控制器的这一部分简单地准备输出,放在一个非常中心的位置,并在包含视图模板之前启动输出缓冲。这样,您可以将输出存储在一个变量中,您可能希望在返回HTTP响应中的内容之前进一步处理该变量。

答案 4 :(得分:0)

我同意tvanfosson,并想解释为什么以及它如何与MVC相关。

第二个示例的问题是控制器暴露于视图的构造方式。从严格意义上讲,控制器会对视图的输入进行封送处理并将其传递给它,而不再是它。

实际的思考方式是,视图是否会根据应用要求或输入本身而变化。例如,如果生成的视图是针对JavaScript弹出窗口的,那么它可能(并且可能会)使用不同的页眉,页脚,CSS,元组等。对于第二个示例,所有暴露给控制器的都是。在你的第一个视图中,谁知道如何生成视图 - 这正是重点。

为了进一步发展我的例子,想象一下JavaScript弹出窗口被重新设计为完整页面视图,或者被重构为AJAX(或弹出/页面/ AJAX问题由输入决定,例如隐藏字段中的元素)。现在你正在拆开控制器,因为视图已经改变了。这并不是说你违反了MVC,但你首先不应该为此烦恼。

答案 5 :(得分:0)

如果您的所有文件名都与您的视图/页面请求相匹配,如示例所示,那么您只需要一行而不需要switch语句:

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

答案 6 :(得分:-2)

如果您使用直接PHP页面作为模板,您实际上可以设置一个全局/会话变量来保存您想要的页面。您将拥有一个“主模板”php页面,其中包含页眉和页脚元素,然后调用$ page的include。在控制器中有类似的东西:

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

然后在main.php模板文件中:

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