3

このチュートリアルhttp://johnsquibb.com/tutorials/mvc-framework-in-1-hour-part-oneに従って、最初のMVCブログを書こうとしています。

仕組みがわかったので、router.php は適切なページコントローラーを呼び出します。このコントローラーはモデルを呼び出し、次に返された値で View ページを呼び出します。

私の質問は、同じ news.php ページにヘッダー\フッターを追加したい場合です。通常は "include("header.php") と記述しますが、MVC を使用する場合、どのように実装すればよいでしょうか?

これらは私のファイルです:

ルーター.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>
4

2 に答える 2

5

問題の一部は、チュートリアルに MVC にインスパイアされたデザイン パターンのかなり原始的な解釈があることです (実際には、PHP で従来の MVC を実装することはできませんが、それに基づくパターンがあります) 。

ビューは単なるテンプレートではありません。ビューは、すべてのプレゼンテーション ロジックを含み、複数のテンプレートを処理するクラス インスタンスであると想定されています。実際にあるのは、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();
}

また、ビュー インスタンスが行うべきことの 1 つは、モデル レイヤーからの情報を要求することです。

役立つと思われるいくつかの資料:

また、OOP の知識を広げたい場合は、この投稿に推奨される講義と書籍のリストが含まれています。

于 2012-08-03T16:15:53.057 に答える
2

そのための MVC 構造に適切な解決策はありません。すべてのフレームワークで解決策を見つけることができます。たとえば CakePHP では、リクエストごとに常に呼び出されるコントローラーである AppController を使用できます。ベースコントローラーの一種。

しかし、いいえ、あまりいいことではありません。

最も簡単な方法は、ビューから直接データを取得することです。奇妙に聞こえますが、MVC 構造で受け入れられます。したがって、ビューで $News->getLatestItems(10); を呼び出します。そして彼らと協力してください。

私はそれが好きではありませんが、うまくいきます。

多くのウィジェットとブロックがある場合、MVC だけでは適切な構造ではない可能性があります。次に、MVC の派生物であるhttp://techportal.inviqa.com/2010/02/22/scaling-web-applications-with-hmvc/のようなものを見ることができます。

ますます見られるもう 1 つのソリューション: AJAX 呼び出しを介してリクエストします。したがって、ページが読み込まれた後にそれらを読み込むだけです。そうすれば、1 つの MVC リクエストが複数の MVC リクエストになるため、問題も解決します。

于 2012-08-02T15:48:03.840 に答える