【发布时间】:2017-05-09 01:07:37
【问题描述】:
我正在处理的一个项目中遇到了一些(主要)性能问题,在记录了所有执行的查询后,我意识到其中许多查询被执行了多次,我无法找到问题的根源。
所有多次执行的查询都在我看来作曲家提供者。
这是我的视图作曲家的样子:
public function boot()
{
view()->composer('partials.sidebar', function ($view) {
$currentCategory = $this->getCurrentCategory();
$sidebarCategories = SidebarCategory::category($currentCategory)
->order()
->get();
$view
->with('sidebarCategories', $sidebarCategories);
});
view()->composer('partials.footer', function ($view) {
$footerLinks = FooterCategory::with('links.translations')->order()->get();
$footerColumn1 = $footerLinks->filter(function ($value, $key) {
return $value->column == 1;
});
$footerColumn2 = $footerLinks->filter(function ($value, $key) {
return $value->column == 2;
});
$footerColumn3 = $footerLinks->filter(function ($value, $key) {
return $value->column == 3;
});
$footerColumn4 = $footerLinks->filter(function ($value, $key) {
return $value->column == 4;
});
$view
->with(compact('footerColumn1', 'footerColumn2', 'footerColumn3', 'footerColumn4'));
});
}
这两个查询(Sidbar 和 Footer 类别)都会执行大约 6 次,即使每个部分只被调用一次。它们都在主视图中使用 @include('partialname') 调用。
我试过了:
if($view->offsetExists('sidebarCategory'))
return;
但是 offsetExists 总是返回 false(即使在它调用了 5 次之后)。
知道为什么会发生这种情况以及我做错了什么吗?
编辑:
我已经意识到问题出在哪里。在我正在访问的页面上(执行多个查询的地方)有大约 404 个元素(主要是图像)。每次找不到文件时,都会引发新的 404 异常。每次抛出 404 异常时,都会执行 404 视图 => 意味着页脚/侧边栏查询也会执行(因为它们是 404 视图的一部分)。示例:http://imgur.com/a/RrmOD
所以后续问题是如何防止视图在不需要时被渲染(例如 404 是未找到的图像)。
这是我的路线中的一段代码,我认为这是发生这种情况的原因:
Route::get('{slug}', ['as' => 'findBySlug', 'uses' => function($slug) {
if(\App\DynamicCategory::findBySlug($slug)->count() > 0)
return App::make('App\Http\Controllers\GeneralController')->getDynamicCategoryIndex($slug);
else if(\App\DynamicPage::noCategory()->findBySlug($slug)->count() > 0)
return App::make('App\Http\Controllers\GeneralController')->getDynamicPage($slug);
else
abort(404);
}]);
PS:我知道这段代码非常未优化(因为它基本上执行了两次相同的查询,一次是查看项目是否存在,另一次实际上是在控制器中)。这是正在进行的工作,它在待办事项列表中。
编辑 2:
我提出了下一个解决方案,我愿意改进,因为这是一种有点 hack-ish 的方式(如果我添加更多文件夹,我还需要记住更新它)。我在公用文件夹中只有 3 个直接子文件夹:东西、文件和资源。
解决方案是在呈现异常时检查 url 的第一段(在文件 app/Exceptions/Handler.php 中),如果它与 3 个文件夹中的一个匹配,则返回不带视图的 404 响应:
public function render($request, Exception $e)
{
$firstSegment = $request->segment(1);
if(starts_with($firstSegment, 'files') || starts_with($firstSegment, 'something') || starts_with($firstSegment, 'resources')) {
return response('Stran ne obstaja', 404);
}
return parent::render($request, $e);
}
提前致谢
【问题讨论】:
-
在您的情况下,最好从错误页面中排除导致多次查询的内容。您可以通过在刀片主布局中使用 if/else 并在不应呈现内容时传递变量来轻松完成此操作。
-
这不是一个简单的解决方案,因为我有大量的视图,并且在显示文件之前检查每个图像是否确实存在也会导致性能问题。
-
不不,我的意思是你可以在调用 404.blade.php 时排除它。
-
哦,我明白你的意思了。我会从 404 视图中删除 sidbar/footer。不幸的是,这不是我的决定,而是我的客户想要那样(阅读:我无法改变:/)
-
也许,我说也许,您可以将这些查询的结果缓存在 APC 缓存中,并使用来自缓存而不是来自真实数据库的数据呈现 404 页面。