在控制器中包含标题,菜单和页脚

时间:2014-06-15 14:31:36

标签: php controller include footer

我正在创建我自己的原始MVC(或MVP,有些人可能称之为)框架,我想知道在我的控制器中包含页眉,页脚和其他任何内容的最佳实践方法。

目前,我在每个控制器的末尾执行以下操作:

class Index extends Controller
{
    public function index()
    {
        $hData = array(
            'title'       => 'Home',
            'stylesheets' => array(
                'style1.css',
                'style2.css'
            ),
            'javascripts' => array(
                'script1.js',
                'script2.js'
            )
        );

        $cData = array(
            'heading' => 'My first PHP application',
            'message' => 'Hello, world!'
        );

        //HTML Output
        $header  = new View('/views/header.php');
        $html    = $header->fetch($hData);

        $menu    = new View('/views/menu.php');
        $html   .= $header->fetch();

        $content = new View('/views/index.php');
        $html   .= $content->fetch($cData);

        $footer  = new View('/views/footer.php');
        $html   .= $footer->fetch();

        echo $html;
    }
}

我是正确地做了还是有更好的方法呢?如果是这样,我会非常感谢一个例子。

4 个答案:

答案 0 :(得分:1)

通常,自己构建MVC框架会迫使您接受一些妥协。但这就是我的想法:

  1. 你应该有一些模板引擎(理想情况下,可能是可替换的)。它可以是PHP,也可以是已经存在的(Twig,Smarty)

  2. 控制器应该只知道模板引擎将呈现的特定视图。因此,视图应该可以通过名称而不是模板文件的具体路径来获取。

  3. 模板引擎应该知道如何将模板名称解析为真实的模板文件。

  4. 模板引擎应该能够接受模板的变量,可以从控制器传递给它。

  5. 包括页眉,页脚等,应该由模板引擎或模板中考虑,但不能在控制器中考虑。例如,您的代码可能支持显示部分内部html的AJAX调用。在这种情况下,模板的名称可以是相同的,但是根据从控制器传递的一些var,模板引擎(或模板本身)可以显示正常请求的页眉和页脚,并为ajax请求省略它们。 / p>

  6. 当然,以硬编码方式定义哪个css文件加载到模板中不是控制器的任务。但是,可能是一些系统设置,可以在控制器中读取,然后作为变量传递给模板。

  7. 2和3可以是可选的,如果你不需要额外的灵活性,或者你很确定你以后不需要切换到Smarty或Twig。

答案 1 :(得分:1)

MVC专门用于分离功能。

模型 - 将此视为您的应用层。在设计模型时,它就是应用程序本身。你需要什么内容?这通常以原始形式返回。数组,对象,JSon等。

查看 - 视图是您提供数据的方式。 PHP是一个很棒的模板引擎,但还有其他的,如SmartyTwig,它们基于PHP,专为模板设计。查看它们,看看你的想法。我个人使用Smarty,正在研究Symfony(一个使用Twig进行视图的MVC框架),用于未来的潜在项目。但是很多人说PHP单独工作就好了。每个人都有利有弊。

控制器 - 控制器告诉程序要做什么以及去哪里。这是您的业务逻辑层。您的Front Controller位于您的模型和视图之间,以便将正确的内容放到正确的位置。

因此,在考虑页眉和页脚时,请考虑它们的属性。最后,因为它是模板和图像的问题,它可能最适合在视图中。

编辑:视图示例

如果您选择使用PHP作为模板,您可以从最基本的(难以扩展)一直到从头开始的高度动态的面向对象的模板引擎。根据您的项目范围,我将再次强烈建议您至少在Smarty或Twig上查看作为选项。

简单模板:用户个人资料 模板可以像这样简单:

<?php include("header.html.php");
 /*I am using .html because you can also create .xml views.
      The beauty of MVC is you can create multiple views with 
      the same model, just having your controller direct 
      to the correct view. */ ?>
<!-- Your content here -->
    <div id="userPicture"><img src="<?php echo $userPictureLocation; ?>"></div>
    <div id="userDetails">
        <div id="userName">
            <span class="key">Name:</span>
            <span class="value"><?php echo $userNameValue; ?></span>
        </div>
        <div id="userBio">
            <span class="key">Bio:</span>
            <span class="value"><?php echo $userBioValue; ?></span>
        </div>
    </div>
<!-- End Content -->
<?php include ("footer.html.php"); ?>

使用这个非常简单且难以维护的模板系统,您只需在前端控制器中使用include $file;

如果要创建面​​向对象的视图而不使用像Smarty或Twig这样的模板引擎,那么您将需要创建自己的对象类。您可以查看Smarty和/或Twig的功能,以了解所需的内容。它正在重新发明轮子,但重新发明轮子是一个很好的学习工具。但是,您可以做的一件非常简单的事情是添加一个具有函数setValue()getValue()load()的Template类。 load()setValue()可以在您的模板中使用,getValue()可以在您的模板中使用。

class template {
    private $values;

    public function __construct() {
        $this->values = array();
    }

    public function setValue($key, $value) {
        $this->values[$key] = $value;
    }

    public function getValue($key) {
        return $this->values[$key];
    }

    public function load($file) {
        //The APPLOCATION constant below would be under a configuration
        //file define('APPLOCATION','/var/www/html/'); or whatever your app location
        //is. A Registry Class is probably a better bet for a large application and is
        //the best practices way to do it.
        include APPLOCATION . "template/{$file}";
    }
}

这个类非常轻量级但也可以添加到。它可以防止一些更恶劣的复制,并且可以通过有限的努力进行扩展。

再一次,我们之前看过的模板,这次是使用Template对象。

<?php 
//In this example I am assuming you declared a new Template 
//in your Controller and assigned it the value of $template.
$template->load("header.html.php");
?>
<!-- Your content here -->
    <div id="userPicture"><img src="<?php echo $template->getValue('userPictureLocation'); ?>"></div>
    <div id="userDetails">
        <div id="userName">
            <span class="key">Name:</span>
            <span class="value"><?php echo $template->value('userNameValue'); ?></span>
        </div>
        <div id="userBio">
            <span class="key">Bio:</span>
            <span class="value"><?php echo $template->value('userBioValue'); ?></span>
        </div>
    </div>
<!-- End Content -->
<?php $template->load("footer.html.php"); ?>

答案 2 :(得分:0)

您是否考虑过创建一个printView方法,该方法将您的两个参数包装起来并将其包裹起来?如果你真的想要没有理由你需要指定脚本,如果它们不会改变的话。类似的东西:

class Controller {

    // Protected makes it visible to children, but not to callers
    protected function printHTML($bodyPage, $bodyData = array(), $altHeaders = array()){
        $defaultHeaders = array(
            'title'       => 'Home',
            'stylesheets' => array(
                'style1.css',
                'style2.css'
            ),
            'javascripts' => array(
                'script1.js',
                'script2.js'
            )
        );
        $trueHeaders = array_merge_recursive($defaultHeaders, $altHeaders);

        $header  = new View('/views/header.php');
        $html    = $header->fetch($trueHeaders);

        $menu    = new View('/views/menu.php');
        $html   .= $header->fetch();

        $content = new View($bodyPage);
        $html   .= $content->fetch($bodyData);

        $footer  = new View('/views/footer.php');
        $html   .= $footer->fetch();

        echo $html;
   }
}

class Index extends Controller {
    public function index() {
        $this->printHTML(
            '/views/index.php',
            array(
                'heading' => 'My first PHP application',
                'message' => 'Hello, world!'
            ),
            array(
                'title' => 'My Index Page',
                'stylesheets' => array(
                    'style3.css'// Will use styles 1, 2 and 3 because we merge the array recursively.
                )
            )
        );
    }
}

答案 3 :(得分:0)

创建一个名为layout的文件夹,放置一个名为Header的文件和一个名为footer的文件,并将所有标记放到内容div中,然后在header.php之后需要View.php的视图文件然后放置页脚。 php并在文件后需要并关闭所有标签。我就是这样做的。