【问题标题】:Learning MVC design pattern, but has trouble understanding how to for example render sidebars with dynamic content学习 MVC 设计模式,但难以理解如何使用动态内容呈现侧边栏
【发布时间】:2015-08-31 18:46:25
【问题描述】:

我正在学习使用 MVC 作为设计模式编写 php。我确实认为我非常了解角色控制器、模型和视图的方式和内容。

但我似乎遇到的主要问题是如何实际布局页面。 对我来说一个典型的页面示例是。

一个看起来像这样的路由器:

Route::('/blogg/[id]', 'controllers/blogg@read');

稍后,在控制器中它可能会这样说:

public function read($id) 
{
   $this->model->getPost($id);

   View::renderHtml('header', $data);
   View::render('views/blogg/post', $data);
   View::renderHtml('footer', $data);
}

好的,到目前为止,一切都很好。在我的脑海中,一切看起来都干净利落。例如,这将使页面看起来像图片上的示例 B。导航栏在“renderHtml('header')”视图内的位置...

但是,如果我希望我的页面看起来像示例 F。两个侧边栏位于屏幕的两侧。我该怎么做呢?

让我们尝试一下侧边栏包含不同的可重用小部件的想法。像 Twitter Feed,或“热门博客文章”或其他任何东西。并且不同的页面,甚至不同的博客文章会动态地将不同的小部件或信息加载到两个侧边栏中。

这仍然是这个控制器的责任吗?我是否应该简单地做这样的事情:

public function read($id) 
{
   $this->model->getPost($id);

   View::renderHtml('header', $data);
   View::renderPartial('sidebar-left', $data);
   View::render('views/blogg/post', $data);
   View::renderPartial('sidebar-right', $data);
   View::renderHtml('footer', $data);
}

我根本不喜欢这个解决方案。因为突然之间,我刚刚学到的干净的 MVC 模式……似乎又变成了这个大烂摊子。

所以...例如,谁来渲染侧边栏。谁应该动态地用内容填充侧边栏。所有这些在哪里结合在一起!?我的意思是,我不应该在每个视图中重新创建侧边栏,对吧?例如,我将有许多不同的页面将侧边栏用于完全不同的目的。

为了记录,我正在使用一个框架,但不是像 Laravel 或 CakePHP 这样的大框架......一个更小的框架。我真的很喜欢它,所以我更想学习...... MVC 这样做的方式,而不是仅仅被推荐使用 Laravel 或其他东西。不过,请告诉我 Laravel 或其他大型框架如何处理这个问题。我相信有很多方法可以解决这个问题。

【问题讨论】:

  • 在大多数框架中,您只需将数据向下传递,然后让主视图决定在哪里呈现部分......
  • 什么是主视图?就像一个决定天气的主视图/布局一样,此页面上是否有侧边栏?就像一个包含所有可能事物的视图,例如左侧边栏、右侧边栏、导航栏、内容等?那么控制器将如何传递,让我们说侧边栏左侧到主视图呢?它如何告诉它侧边栏需要显示什么?

标签: php html model-view-controller


【解决方案1】:

在适当的 MVC 架构中,任何输出(包括模板)在技术上都属于视图。但是,我们经常会做一些修改,在控制器中定义主题/布局以减少视图中的代码重复。

作为一般经验法则,出现在页面中的可重用内容(例如评论部分)将作为模板嵌入到视图中。但是,包装内容(例如导航或<head> 块)将由(抽象)控制器在后台处理。

如果我从头开始编写框架,我可能会这样做的一种方法是提供抽象控制器类 _beforeRender()_afterRender() 挂钩,您可以在每个控制器中覆盖它们。然后,您可以将要包含在该特定控制器内每个页面上的任何导航元素(例如左侧和右侧边栏)定义为模板,并在每个控制器中显式引用一次,而不是在每个操作中。例如:

/**
 * Applies header and footer to all views, but can be overridden by controllers
 */
abstract class Controller {
    public function _beforeRender($data) {
        View::renderHtml('header', $data);
    }
    public function _afterRender($data) {
        View::renderHtml('footer', $data);
    }
}

class BlogController extends Controller {
    public function post($id) {
        // View will automatically call _beforeRender and _afterRender
        View::render('views/blog/post', $data);
    }
    public function _beforeRender($data) {
        parent::_beforeRender($data);
        View::renderPartial('sidebar-left', $data);
    }
    public function _afterRender($data) {
        View::renderPartial('sidebar-right', $data);
        parent::_afterRender($data);
    }
}

【讨论】:

  • (在“正确的”MVC 中,视图实际上是活动组件。只有 PHP 网络框架,其中视图主要是单向 C→M→V 管道中的数据坑。)
  • 嗯...有趣的做法。但是,假设侧边栏只显示给登录的人呢?还有一个问题...我现在渲染侧边栏-左...它怎么知道要显示什么?假设 BlogController 和 UserProfileController 都有一个侧边栏。同样的局部视图如何知道在其内部渲染什么?
  • 这就是为什么你会在每个控制器上使用不同的_beforeRender() 方法,并让它们引用不同的模板。否则,您只需将标题和侧边栏放在同一个模板中。不过,马里奥是正确的。这是与纯 MVC 架构的常见偏差。
猜你喜欢
  • 2015-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多