【问题标题】:PHP MVC - Template / Loading variables IssuePHP MVC - 模板/加载变量问题
【发布时间】:2012-07-24 08:19:50
【问题描述】:

我正在 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'; 时视图不会加载它,因为 template.class 被绕过了。基本上我要问的是如何将 template.class 转移到加载函数中?

【问题讨论】:

  • 像你正在做的那样在路由类中选择一个视图模板是个坏主意。您不仅假设每个操作都会始终呈现一个视图,而且该视图只能有一个模板。具有模板和从动作级别分配的变量的单独视图对象是更好的解决方案。

标签: php oop model-view-controller variables


【解决方案1】:

“视图只是一个愚蠢的模板”这个非常普遍的误解主要是由 Ruby-on-Rails 和那些遵循其损坏的 ORM-Template-Adapter 的。我不能直截了当地将它们实现为 Model-View-Controller ...

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

根据您在 Web 应用程序中使用的受 MVC 启发的模式(使用 PHP 实现经典 MVC 是不可能的),您的视图要么从类控制器结构(在 MVP 和 MVVM 模式中)接收数据,要么能够请求直接来自模型层的信息(Model2 MVC 和 HMVC 模式)。我个人更喜欢从模型层获取数据的活动视图。

附:像$this->registry->template->blog_heading 这样的代码会使Demeter 流血。

附言如何实现纯php模板,请阅读this article

【讨论】:

  • 您发送的链接信息量很大,并且符合我的最终目标。对于php模板链接,教程名为“$view->render('main.php');”我如何能够将我的系统设置为自动渲染,而不是每次都手动输入?
  • 您可以通过为对象实现__toString() 方法来模仿它,然后您可以只使用echo $view; 并触发该方法。但我建议避免它。最好有详细的代码,然后添加隐藏的魔法。此外,该链接的部分原因是向您展示,您所学的“视图”实际上是一个模板。这将导致表示逻辑泄漏到控制器中。
  • 好的,谢谢!我想这是一种更真实的 MVC 逻辑形式,所以我应该坚持下去。再次感谢您指出模板概念。干杯!
  • 您可能还会发现this comment 很有用。
【解决方案2】:

我知道这对你现在没有多大帮助,但几个月前我也遇到过同样的问题。这是基于我构建的框架:

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;

【讨论】:

  • 我去看看,希望是我要找的。​​span>
  • 你需要的东西肯定在那里,这只是调整它以适应你自己的框架的情况,因为我确信它的行为非常不同。
  • 找到它设置变量的位置,然后决定要渲染的变量:github.com/andyhmltn/Cherry-Framework/blob/master/library/…
  • 这看起来像我需要的。我只需要像你的那样重组我的模板文件然后正确吗?没有别的吗?
  • 看起来是的。该文件只是扩展变量,然后加载模板文件
【解决方案3】:

在我自己开发的 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();
         }
    }

}

【讨论】:

  • 虽然这解决了变量的问题,但我认为 OP 想要它,以便根据控制器操作自动加载视图。我家里有这样的东西,我回来后会发布,但我想到那时就会得到答复哈哈
  • 哈哈,好吧。我添加了一个名为 _no_action 的方法,表示如果没有对应于视图文件的显式操作,则调用它。
  • 这行得通,但我要说的唯一一件事是你需要把它放在调用控制器的部分。这样,如果您有 50 多个控制器,您就不必重复该代码哈哈。除此之外,它的工作原理!
  • 没错,它可能应该是父控制器的一部分,_no_action 应该只是对应于控制器应该独立于正常的“如果没有操作则加载文件”操作执行的特殊操作。动作动作动作。
猜你喜欢
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
相关资源
最近更新 更多