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

Php Yii框架:出现在每个页面上的菜单内容,php,yii,Php,Yii,我正在使用Yii框架开发一个使用两列布局的站点。一列是实际内容,另一列是包含站点链接、有关登录用户的一些信息和最新帖子列表的菜单。菜单出现在所有页面上,但没有与当前页面(或路线)相关的信息 每次渲染菜单时,我都需要从数据库中检索最新帖子和用户相关数据的列表。我不确定如何最好地呈现这个菜单,这样我就不会重复在站点上的每个操作中获取数据的代码 我想到了几种方法,我想知道哪一种(如果有的话)是处理这种情况的正确方法 在Controller::beforeRender方法中获取数据,然后在局部视图中呈

我正在使用Yii框架开发一个使用两列布局的站点。一列是实际内容,另一列是包含站点链接、有关登录用户的一些信息和最新帖子列表的菜单。菜单出现在所有页面上,但没有与当前页面(或路线)相关的信息

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

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

  • Controller::beforeRender
    方法中获取数据,然后在局部视图中呈现菜单,该视图在
    CClipWidget
    块中显示数据。然后,在布局视图中,显示菜单应该位于的块。这个方法是有效的,但我觉得它相当笨拙,因为在渲染之前有
    。如果我添加了一个没有菜单的页面,我需要包括一个检查。另外,在阅读了Yii文档之后,我不明白是为
    renderPartial()
    调用
    beforeRender()
    ,还是仅为
    render()
    调用

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

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


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

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

$posts = Post::model()->cache(600)->with('comments')->findAll(array('blah=blahdyblah'));
这将缓存返回的数据10分钟

这里有一个指向Yii缓存指南的链接,仅供参考:

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

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

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

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

  • 最后,如果您确实希望使用来自小部件的“部分”数据,而不是全部数据,或者稍微更改它,那么您在小部件中使用的方法和视图应该具有足够的抽象,以便您可以单独使用所需的部分。这样做的一个好方法是充分利用ActiveRecords、mini view文件上的
    作用域
    ,并将组件用于更大的非数据逻辑块


当然,如果您运行的性能非常有限,需要将请求时间缩短千分之一秒,那么您应该研究视图缓存并使用:

CWidget的render()函数不使用任何布局。所以你不需要任何renderPartial()是的,我知道这一点。我在想,我可能还需要从控制器呈现“最新帖子”视图。我会使用小部件不支持的
renderPartial()。因此,我必须编写一个单独的视图(或者将“最新帖子”本身变成一个小部件)。事实上,缓存是一种有用的技术。谢谢你的指导。然而,我更感兴趣的是编写优雅的代码,而不是重复我自己。我想知道我应该在哪里获取数据,以便在每一页上都能找到。非常感谢!我倾向于小部件方法,但这确实说服了我。