Yii 框架:出现在每个页面上的菜单内容


Yii Framework: Menu content that appears on every page

我正在使用Yii框架来开发一个使用2列布局的网站。一列是实际内容,而另一列是带有站点链接的菜单,有关登录用户的一些信息和最新帖子的列表。菜单存在于所有页面上,但它没有与当前页面(或路由)相关的信息。

每次渲染菜单时,我都需要从数据库中检索最新帖子和用户相关数据的列表。我不确定如何最好地呈现此菜单,以便我不会重复在站点上的每个操作中获取数据的代码。

我想到了几种方法,我想知道其中哪一种(如果有的话)是处理这种情况的正确方法。

  • Controller::beforeRender 方法中获取数据,然后在分部视图中呈现菜单,该分部视图在CClipWidget块中显示数据。然后,在布局视图中,显示菜单应该所在的块。这种方法有效,但由于beforeRender,我觉得它很笨拙。如果我添加了一个没有菜单的页面,我需要包括一个检查。另外,在阅读了 Yii 文档后,我不明白beforeRender()是否也用于renderPartial(),或者只是为了render()

  • 保留菜单的部分视图,并从布局视图呈现它。数据在菜单视图中从放置在其他位置(可能在模型中)的静态方法获取。这涉及编写很少的代码,但我不确定这是否是 MVC 范式的好做法。在视图中获取数据让我有点畏缩,即使它只是调用一个静态函数。

  • 将菜单变成小部件。数据在 run() 方法中获取并从小组件视图呈现。但是,使用小部件会施加一些额外的限制。如果我想使用在控制器中呈现最新帖子的视图,我会遇到问题。小部件不能使用renderPartial(),并且被迫一直使用render()。如果我弄清楚如何检查渲染视图(小部件或控制器)的内容并适当地调用render()renderPartial(),我可以解决此问题。此外,小部件视图必须与站点视图分开,但我可以通过指定完整的视图路径来解决这个问题,例如 application.views.controller.view ,尽管它可能很笨重。此外,我仍然不确定小部件是否应该自己获取数据库数据。

所有这些方法都有效,但它们都有一些问题。我相信许多网站都处于相同的情况,我想看看最好的选择是什么。

您应该能够通过简单地缓存数据库结果(在内存中还是在文件中由您和您的设置)来避免重新请求此数据的大部分性能影响。下面是一个简单小的例子:

$posts = Post::model()->cache(600)->with('comments')->findAll(array('blah=blahdyblah'));

这将缓存返回的数据 10 分钟。

这里再次链接到 Yii 缓存指南,只是为了完整起见:缓存指南

为了在每个页面上实际获取这些数据,您最好将代码放在您自己的小部件中,并在布局文件中的某个位置调用它。

您可以处理您列出的小部件限制:

  • 首先,当小部件渲染时,它只会render(),但没有布局。这在大多数情况下都很好,但是如果您确实想要一个只打开它的页面,比如说您想要一个真正的render(),然后这样做,只需创建一个仅调用该小部件的视图即可。

  • 其次,没有
  • 理由必须从应用程序中完全抽象小部件,而不使用其数据+模型。是的,它们可以"可插拔"是一个非常好的功能,但这并不意味着它们必须是,你只是使用它们来分离代码。

  • 最后,如果您确实想使用小部件中的"部分"数据,但不是全部,或者稍微更改一下,那么在小部件中使用的方法和视图应该使用足够的抽象来构建,以便您可以单独使用所需的部分。执行此操作的一个好方法是充分利用 ActiveRecord 上的scopes、迷你视图文件,并将组件用于更大的非数据逻辑块。

当然,如果您确实在性能极限上运行并且需要将请求时间缩短千分之一秒,那么您应该研究视图缓存并使用视图的片段缓存: