【问题标题】:pass a variable from controller, through a model to a view file将变量从控制器通过模型传递到视图文件
【发布时间】:2013-09-24 19:25:40
【问题描述】:

我试图了解传递变量是如何工作的。

我已经设置了一个控制器:

class indexController
{
    public function calling()
    {
        $route = new Route():
        $route->title = 'Register user';
        $route->getview('users','register');
    }
}

还有一个模型:

class Route
{
    public function getview($module,$filename)
    {
        require_once('templates/'.$module.'/'.$filename.'.phtml');
    }
}

还有一个类似这样的视图文件:

<div class="title"><?php echo $this->title; ?></div>

如何设置视图的标题?我应该在控制器中“公开”这个 var,并在构建模型以在我的视图文件中使用时获取它吗?

【问题讨论】:

    标签: php oop model-view-controller parameter-passing


    【解决方案1】:

    您的设计存在问题,但忘记这些问题是您可以做到的。

    public function var( $var, $val ) {
        $this->vars[$var] = $val; // should disallow _view as a $var
    }
    
    public function getview($module,$filename)
    {
        $_view = 'templates/'.$module.'/'.$filename.'.phtml';
        extract( $this->vars );  //creates variables for 
        require_once( $_view );
    }
    

    这样使用

        $route = new Route():
        $route->var( 'title', 'Register user' );
        $route->getview('users','register');
    

    【讨论】:

    • 路由器甚至不应该知道模板和视图!!!其目的是确定是否有URI 与某种路由图匹配。仅此而已。你在这里做的事情违反了单一职责原则
    • @DaveJust 我同意,这就是为什么我的第一句话指出他的设计存在问题。
    • 为什么将模板称为“视图”?
    【解决方案2】:

    是什么让您觉得您正在实施 MVC?因为从目前的情况来看,您似乎混淆了模式每个部分的职责。

    这里是基础知识..

    MVC 是一种架构设计模式,即SoC 原则的表达。它将模型层(负责实现领域业务逻辑)与表示层分开。在表示层中,它将处理用户输入的部分(控制器)与生成用户界面(视图)的逻辑分开。

    将这种模式应用到 Web 时,信息流是这样的:

    • 控制器接收用户请求
    • 控制器改变模型层的状态和(可能)当前视图
    • 从模型层查看请求必要信息
    • 视图对用户产生响应

    你所拥有的不是视图,而只是一个模板。你所拥有的不是模型,而只是一个类。

    现在你的问题是:

    如何设置视图的标题?

    您的视图应该从模型层请求它需要的信息:

    namespace Views;
    
    class Doclument 
    {
        // ... some code
    
        public function foobar()
        {
            $library = $this->serviceFactory->acquire('Library');
    
            $title = $library->getCurrentDocument('title');
            $content = $library->getCurrentDocument('content');
            
            $this->template['main']->assign([
               'title' => $title,
               'body'  => $content,
            ]);
        }
    
        // ... some more code 
    
        public function render()
        {
           /*
               if any templates have been initialized,
               here you would put code for combining them and
               return html (or some other format)
           */
        }
    }
    

    当然,您需要知道用户想要查看的文档......应该在控制器中完成:

    namespace Controllers;
    
    class Document
    {
        // ... again, some code, that's not important here
    
        public function getFoobar( $request )
        {
            $library = $this->serviceFactory->acquire('Library');
            $library->useLanguage( $request->getParameter('lang') );
            $library->locateDocument( $request->getParameter('id') );
        }
    }
    

    $serviceFactory 将在控制器和视图之间共享,因为这是您与模型层交互的方式。这也为您提供了一种只初始化每个服务一次的方法,而不会创建对全局状态的依赖。

    我应该在控制器中“公开”这个变量,并在构建模型时获取它以在我的视图文件中使用吗?

    没有。

    模型层(是的,它应该是层并且不是类)不应该知道表示层实现的任何事情。实际上,视图也不应该知道控制器的。

    实际上,在 OOP 中使用公共变量被认为是一种不好的做法(除非您正在创建数据结构......想想:像二叉树这样的东西)。它会使您的代码变为leak encapsulation。

    附言

    我试图了解传递变量是如何工作的。

    这是面向对象编程的基础知识。如果您没有很好地掌握 OOP 的概念、实践和方法,则不应该玩弄像 MVC 模式这样的高级结构。

    查找名为“依赖注入”的东西。

    【讨论】:

    • 我想知道,投票者能否解释原因,为什么这个答案在某种程度上是错误的/不好的。
    猜你喜欢
    • 1970-01-01
    • 2012-02-10
    • 2013-11-20
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多