我正在使用Yii框架开发一个使用2列布局的网站。一列是实际内容,另一列是带有站点链接的菜单,有关登录用户的一些信息和最新帖子的列表。菜单出现在所有页面上,但没有与当前页面(或路线)相关的信息。
每次渲染菜单时,我都需要从数据库中检索最新帖子和用户相关数据的列表。我不确定如何最好地渲染此菜单,以便我不会重复在网站上的每个操作中获取数据的代码。
我想到了一些方法,我想知道其中哪一个(如果有的话)是处理这种情况的正确方法。
获取Controller::beforeRender
方法中的数据,然后在局部视图中呈现菜单,该视图在CClipWidget
块中显示数据。然后,在布局视图中,显示应该是菜单的块。这种方法有效,但我觉得因beforeRender
而非常笨重。如果我添加一个没有菜单的页面,我需要包含一个检查。此外,在阅读Yii文档后,我不理解beforeRender()
是否也被renderPartial()
调用,或仅仅render()
。
保留菜单的部分视图并从布局视图中呈现它。在菜单视图中从放置在其他位置的静态方法(可能在模型中)中获取数据。这涉及编写非常少的代码,但我不确定它是否适用于MVC范例。在视图中获取数据让我有点畏缩,即使它只是调用静态函数。
将菜单变为小部件。数据在run()
方法中获取并从窗口小部件视图呈现。但是,使用小部件会产生一些额外的限制。如果我想使用在控制器中呈现最新帖子的视图,我会遇到问题。窗口小部件无法使用renderPartial()
,并且一直被迫使用render()
。如果我弄清楚如何检查呈现视图的内容(小部件或控制器)并适当地调用render()
或renderPartial()
,我可以解决这个问题。此外,窗口小部件视图必须与站点视图分开,但我可以通过指定完整的视图路径(如application.views.controller.view
)来解决这个问题,因为它可能很笨拙。此外,我仍然不确定小部件是否应该自己获取数据库数据。
所有这些方法工作,但它们都有一些捕获。我相信很多网站都处于相同的情况,我想看看最好的选择是什么。
答案 0 :(得分:1)
您应该能够通过简单地缓存数据库结果(在内存或文件中由您和您的设置决定)来避免重新请求此数据的大部分性能损失。这是一个简单的小例子:
$posts = Post::model()->cache(600)->with('comments')->findAll(array('blah=blahdyblah'));
这会将返回的数据缓存10分钟。
以下是Yii缓存指南的链接,仅用于完整性: Caching Guide
要在每个页面上实际获取此数据,最好将代码放在您自己的小部件中,并将其调用到布局文件中的某个位置。
您列出的小部件限制可以处理:
首先,当窗口小部件呈现时,它只会render()
,但没有布局。这对大多数情况都很好,但是如果你确实想要一个只有那个页面的页面,比如你想要一个真正的render()
,那么就这样做,只需创建一个只调用那个小部件的视图。
其次,没有理由小部件必须完全从您的应用程序中抽象出来,而不是使用其数据+模型。是的,它是一个非常好的功能,它们可以是“可插拔的”,但这并不意味着它们必须是,你只是使用它们来分离代码。
最后,如果您确实想要使用小部件中的“部分”数据但不是全部,或者稍微更改一下,那么您在小部件中使用的方法和视图应该使用足够的抽象来构建可以单独使用你需要的部分。这样做的一个好方法是充分利用ActiveRecords上的scopes
,迷你视图文件,以及使用更大块的非数据逻辑组件。
当然,如果你真的在性能极限上运行并且需要在请求时间内缩短千分之一秒,那么你应该查看视图缓存并使用fragment caching of views: