MVC博客 - 如何包含header \ footer \ other.php文件

时间:2012-08-02 15:27:33

标签: php html sql model-view-controller

按照本教程http://johnsquibb.com/tutorials/mvc-framework-in-1-hour-part-one尝试编写我的第一个 MVC 博客。

我理解它是如何工作的,router.php调用合适的页面控制器。该控制器调用模型,然后使用返回值调用View页面。

我的问题是,如果我想将相同的news.php页面添加到页眉\页脚,该怎么办?通常我会写“include(”header.php“)。但是现在使用MVC时,我该如何实现呢?

这些是我的文件:

  

router.php:

    <?php
/**
 * This controller routes all incoming requests to the appropriate controller
 */
//Automatically includes files containing classes that are called

//fetch the passed request
$pageURL = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
$path_parts = pathinfo($pageURL);
$page_name = $path_parts['filename']; 
$parsed = explode('?' , $page_name);
//the page is the first element
$page = array_shift($parsed);

// If there is any variables, GET them.
if(!empty($parsed))
{
    $parsed = explode('&' , $parsed[0]);
    $getVars = array();
    foreach ($parsed as $argument)
    {
        //explode GET vars along '=' symbol to separate variable, values
        list($variable , $value) = explode('=' , $argument);
        $getVars[$variable] = urldecode($value);
    }
}

//compute the path to the suitable file
$target ='controllers/' . $page . '_controller.php';

//get target controller
if (file_exists($target))
{
    include_once($target);

    //modify page to fit naming convention
    $class = ucfirst($page) . '_Controller';

    //instantiate the appropriate class
    if (class_exists($class))
    {
        $controller = new $class;
    }
    else
    {
        //did we name our class correctly?
        die('class does not exist!');
    }
}
else
{
    //can't find the file in 'controllers'! 
    die('page does not exist!');
}

//once we have the controller instantiated, execute the default function
//pass any GET varaibles to the main method
$controller->main($getVars);


//  AutoLoad
function __autoload($className)
{        
    // Parse out filename where class should be located
    // This supports names like 'Example_Model' as well as 'Example_Two_Model'
    list($suffix, $filename) = preg_split('/_/', strrev($className), 2);
    $filename = strrev($filename);
    $suffix = strrev($suffix);

    //select the folder where class should be located based on suffix
    switch (strtolower($suffix))
    {    
        case 'model':

            $folder = '/models/';
            $filename = ($className);

        break;

        case 'library':

            $folder = '/libraries/';

        break;

        case 'driver':

            $folder = '/libraries/drivers/';

        break;
    }

    //compose file name
    $file = SERVER_ROOT . $folder . strtolower($filename) . '.php';

    //fetch file
    if (file_exists($file))
    {
        //get file
        include_once($file);        
    }
    else
    {
        //file does not exist!
        die("File '$filename' containing class '$className' not found in
'$folder'.");    
    }
}

?>
  

post_controller.php

<?php
    /**
     * This file handles the retrieval and serving of posts posts
     */
    class Posts_Controller
    {
        /**
         * This template variable will hold the 'view' portion of our MVC for this 
         * controller
         */
        public $template = 'posts';

        /**
         * This is the default function that will be called by router.php
         * 
         * @param array $getVars the GET variables posted to index.php
         */
        public function main(array $getVars)
        {
            //$b_controller =new  Bottom_Bar_Controller;
            //$b_controller->main($getVars);

            $postsModel = new Posts_Model;

            //get an post
            $post = $postsModel->get_post($getVars['id']);
            //create a new view and pass it our template
            $header = new View_Model('header_template');
            $bottom_bar = new View_Model('bottom_bar');
            $view = new View_Model($this->template);


            //assign post data to view
            $view->assign('header', $header->render(FALSE));
            $view->assign('bottom', $bottom_bar->render(FALSE));
            $view->assign('title' , $post['title']);
            $view->assign('content' , $post['content']);
            $view->assign('date' , $post['date']);
            $view->assign('by' , $post['added_by']);
            $view->render();

        }
    }
  

posts_model.php

<?php
/**
 * The Posts Model does the back-end heavy lifting for the Posts Controller
 */
class Posts_Model
{
    /**
     * Holds instance of database connection
     */
    private $db;

    public function __construct()
    {
        $this->db = new MysqlImproved_Driver;
    }

    /**
     * Fetches article based on supplied name
     * 
     * @param string $author
     * 
     * @return array $article
     */
    public function get_post($id)
    {        
        //connect to database
        $this->db->connect();

        //sanitize data
        $author = $this->db->escape($id);

        //prepare query
        $this->db->prepare
        (
            "
            SELECT *  FROM `posts`
            WHERE
                `id` = '$id'
            LIMIT 1
            ;
            "
        );

        //execute query
        $this->db->query();

        $article = $this->db->fetch('array');

        return $article;
    }

}
?>
  

view_model.php

<?php
/**
 * Handles the view functionality of our MVC framework
 */
class View_Model
{
    /**
     * Holds variables assigned to template
     */
    private $data = array();

    /**
     * Holds render status of view.
     */
    private $render = FALSE;

    /**
     * Accept a template to load
     */


    public function __construct($template)
    {

        //compose file name
        $file = SERVER_ROOT . '/views/' . strtolower($template) . '.php';


        if (file_exists($file))
        {

            /**
             * trigger render to include file when this model is destroyed
             * if we render it now, we wouldn't be able to assign variables
             * to the view!
             */
            $this->render = $file;


        }        
    }

    /**
     * Receives assignments from controller and stores in local data array
     * 
     * @param $variable
     * @param $value
     */
    public function assign($variable , $value)
    {
        $this->data[$variable] = $value;
    }

    /**
     * Render the output directly to the page, or optionally, return the
     * generated output to caller.
     * 
     * @param $direct_output Set to any non-TRUE value to have the 
     * output returned rather than displayed directly.
     */
    public function render($direct_output = TRUE)
    {

        // Turn output buffering on, capturing all output
        if ($direct_output !== TRUE)
        {
            ob_start();
        }

        // Parse data variables into local variables
        $data = $this->data;

        // Get template
        include($this->render);

        // Get the contents of the buffer and return it
        if ($direct_output !== TRUE)
        {
            return ob_get_clean();
        }
    }

    public function __destruct()
    {
    }
}
  

posts.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="../style/style.css" rel="stylesheet" type="text/css" media="screen" />  
<title> Posts (View)</title>
</head>

<body>
       <div id="main">
        <div class="container">
        <?=$data['header'];?>
            <div id="content">  
                <div class="content-background">
                <h2> <?=$data['title'];?></h2>
                <h4> <?=$data['date'];?> </h4>
                <p><?=$data['content'];?></p>
                </div>

            </div>
         </div>
        </div>


    </body>
</html>

2 个答案:

答案 0 :(得分:5)

问题的一部分是,你的教程对MVC启发的设计模式有一个非常原始的解释(你实际上不能在PHP中实现经典的MVC,但有patterns,它们基于它)

视图不仅仅是一个模板。视图应该是类实例,它包含所有表示逻辑并处理多个模板。您实际拥有的是layout模板,其中包含posts模板。

// class \Application\View\Posts
public function render()
{
    $layout = new Template( $this->defaultTemplateDirectory . 'layout.html');
    $content = new Template( $this->defaultTemplateDirectory . 'posts.html' );

    $layout->assign( 'content' , $content->render() );

    return $layout->render();
}

此外,视图实例应该执行的操作之一是从模型层请求信息。

您可能觉得有用的材料很少:

如果你想在OOP中扩展你的知识,this post包含一系列推荐的讲座和书籍。

答案 1 :(得分:2)

MVC结构中没有好的解决方案。您可以在每个框架中找到解决方案。例如,在CakePHP中,您可以使用AppController,这是一个始终为每个请求调用的控制器。基础控制器的种类。

但不,不是很好。

最简单的一个是直接从视图中询问数据。这听起来很奇怪,但它在MVC结构中被接受。所以在你看来你叫$ News-&gt; getLatestItems(10);并与他们合作。

我不喜欢它,但它有效。

如果你有很多小部件和块MVC单独可能不是正确的结构。然后你可以看看像http://techportal.inviqa.com/2010/02/22/scaling-web-applications-with-hmvc/这样的东西,它是MVC的衍生物。

您会看到越来越多的另一种解决方案:通过AJAX调用请求它。所以只需在页面加载后加载它们。这样你也可以解决这个问题,因为一个MVC请求会变成多个MVC请求。