PHP MVC - 模板/加载变量问题

时间:2012-07-24 08:19:51

标签: php oop model-view-controller variables

我在PHP中创建一个基本的MVC结构化CMS,作为学习MVC如何工作的一种方法(因此我没有使用真正的预构建引擎)。我的基本版本的工作结构与本教程here非常相似。但是,我希望能够自动加载视图,而不需要模板类。如果强烈建议我坚持使用模板概念(如果有人可以解释为什么它是如此必要我会非常感激。)无论如何,下面是我的路由器类,我已经修改为自动加载控制器上的视图文件。

    public function loader() {
        /*** check the route ***/
        $this->getPath();

        /*** if the file is not there diaf ***/
        if (is_readable($this->controller_path) == false) {
            $this->controller_path = $this->path.'/controller/error404.php';
            $this->action_path = $this->path.'/view/error404.php';
        }

        /*** include the path files ***/
        include $this->controller_path;
        include $this->action_path;

        /*** a new controller class instance ***/
        $class = $this->controller . 'Controller';
        $controller = new $class($this->registry);

        /*** check if the action is callable ***/
        if (is_callable(array($controller, $this->action)) == false) {
            $action = 'index';
        } else {
            $action = $this->action;
        }
        $controller->$action();
    }

    /**
    *
    * @get the controller
    *
    * @access private
    *
    * @return void
    *
    */
    private function getPath() {

        /*** get the route from the url ***/
        $route = (empty($_GET['rt'])) ? '' : $_GET['rt'];

        if (empty($route)) {
            $route = 'index';
        } else {
            /*** get the parts of the route ***/
            // mywebsite.com/controller/action
            // mywebsite.com/blog/hello
            $parts = explode('/', $route);
            $this->controller = $parts[0];
            if(isset( $parts[1])) {
                $this->action = $parts[1];
            }
        }
        if( ! $this->controller ) { $this->controller = 'index'; }
        if( ! $this->action ) { $this->action = 'index'; }

        /*** set the file path ***/
        $this->controller_path = $this->path .'/controller/'. $this->controller . '.php';
        $this->action_path = $this->path .'/view/'. $this->controller . '/'. $this->action . '.php';
    }

这阻止我的视图文件加载控制器给出的变量(教程网站有更好的演示)但是在设置$this->registry->template->blog_heading = 'This is the blog Index';时视图没有加载它,因为模板被绕过了.class.class 。基本上我要问的是如何将template.class转换为加载函数?

3 个答案:

答案 0 :(得分:2)

“视图的一个常见错误概念只是一个愚蠢的模板”主要由Ruby-on-Rails和跟随其破坏的ORM-Template-Adapter延续。我不能直面参考他们实现的模型 - 视图 - 控制器......

视图应该处理MVC和MVC启发的设计模式模式中的表示逻辑。这使它们成为对象,能够兼顾多个模板。

根据您用于Web应用程序的MVC模式(使用PHP实现经典MVC是不可能的),您的视图将从类似Controller的结构(MVP和MVVM模式)接收数据,或者能够请求信息直接来自模型层(Model2 MVC和HMVC模式)。我个人更喜欢活动视图,它从模型层获取数据。

P.S。像$this->registry->template->blog_heading这样的代码会导致Demeter出血。

P.P.S。有关如何实现纯php模板,请阅读this article

答案 1 :(得分:1)

在我开发的自己的MVC中,加载视图的工作方式类似于您所拥有的视图,但其方式比您链接到的示例要简单得多。 (当我第一次决定尝试学习MVC时,我看了那个例子,我记得它让我感到困惑x;。

基本上,在确定文件存在之后,您只需要(需要,我觉得找不到文件是在这种情况下停止执行脚本的理由)文件。

所以..而不是整个模板类的东西(我希望我不会躲避你的问题,离开基地太远了,这里有一个控制器打开视图文件的简单例子。

<?php
class Pizza_Shop_Controller extends Base_Controller
{
    public function index()
    {
        $data['users'] = array('bob','lisa','bertha');
        $data['some_string'] = "Whoa I'm a string!";

        $this->render_view('index',$data);
    }

    public function contact()
    {
        if($_POST)
        {
            Contact::process($_POST);
            return $this->render_view('contact_success');
        }
        else
        {
            return $this->render_view('contact_form');
        }
    }


}

class Base_Controller
{

    protected function render_view($view_name,$data = array())
    {
        /*
         * I also think render_view should take care of loading the layout, and then inject the content into the middle of the layout file,
         * so that you aren't trapping yourself to a specific layout, and repeating the header and footer inside of every view file
        */

        extract($data); //places all $data variables into the local scope.. very clean and ezy ;].
        require($this->root_directory.DS."$view_name.php");
    }

    /**********************************/
    public function _no_action($view_name) //Called if there is no corresponding action
    {
        /* You can use method_exists to test if a method exists within the controller, if it does not exist,
         * you can then call this function, and pass it the name of the view that is attempting to be opened
         */
         if($this->view_exists($view_name))
         {
            $this->render_view($view_name,$data);
         }
         else
         {
            $this->render404();
         }
    }

}

答案 2 :(得分:1)

我知道这对你来说并不是非常有帮助,但几个月前我遇到了同样的问题。这是基于我构建的框架:

https://github.com/andyhmltn/Cherry-Framework-Blog-Example/

我不确定它在哪里或如何做到这一点,因为我暂时没有看过它,但是捅了一下,加载控制器的代码,设置变量然后加载视图是可能在库文件夹中。它允许你这样做:

/** Controller **/
class ExampleController extends Controller {
    public function index() {
        $helloworld = 'Hello world';
        $this->set('hello_world', $helloworld);
        #Renders view automatically
    }
}

/** View **/
echo $hello_world;