6

我将其标记为 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;
}

不知何故,我的直觉告诉我这是不正确的。

4

7 回答 7

5

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

于 2008-12-01T01:13:25.757 回答
1

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

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

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

(其中 $page 是 'home'、'search' 等)

于 2008-12-01T02:14:56.647 回答
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 响应中之前进一步处理该变量。

于 2008-12-03T15:24:39.170 回答
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";
    }
}

它背后的想法是你可以写“include 'Template.inc'; new Template;” 它安排 do_output() 在脚本末尾自动运行。它遗漏了一些东西,例如用于将变量传递给模板的方法。

您已经提到您没有使用 PHP,并且其中有一些 PHP 主义: register_shutdown_function() 确保在对象析构函数之前但在主脚本之后调用模板,以及对 $this->header() 的调用/footer() 是只执行 display('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 参数进行切换,那么切换是最安全的方式。

于 2008-12-01T20:49:18.673 回答
0

我同意 tvanfosson 的观点,并想解释它为什么以及它与 MVC 的关系。

您的第二个示例的问题是控制器暴露于视图的构造方式。严格来说,控制器将视图的输入编组并传递给它,仅此而已。

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

进一步举我的例子,假设 JavaScript 弹出窗口被重新设计为一个完整的页面视图,或者为 AJAX 重构(或者弹出窗口/页面/AJAX 问题由输入确定,例如隐藏元素场地)。现在您正在拆开控制器,因为视图已更改。与其说您违反了 MVC,不如说您一开始就不应该为它烦恼。

于 2008-12-09T02:18:04.997 回答
0

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

require "templates/header.php";
require "templates/navigation.php";
require 'views/' . $page . '.php'; // <-- one-liner
require "templates/footer.php";
于 2013-06-06T02:36:12.823 回答
-2

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

$_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";
于 2008-12-01T16:39:31.020 回答