我在一个项目上遇到了一些(主要的)性能问题,我记录了所有执行的查询后,我意识到其中很多都被执行多次,我无法找到问题的根源
多次执行的所有查询都在我的视图编辑器提供程序中。
这是我的视图作曲家的样子:
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:
我已经提出了下一个解决方案,我可以接受改进,因为这是一种有点黑客的方式(如果我添加更多文件夹,我需要记住将其更新为好)。我在公共文件夹中只有3个直接子文件夹:东西,文件和资源。
解决方案是在呈现异常时(在文件app / Exceptions / Handler.php中)检查url的第一个段,如果它与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);
}
提前致谢
答案 0 :(得分:5)
不要通过laravel路由文件请求并在404
上提供空白图像.htaccess样本:
RewriteEngine On
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png|ico)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .*$ /no_picture.png [L]
您可以在重定向到index.php的规则上面发布此内容
这假设图片是从网站提供的,而不是通过流式数据库内容提供的。
基本上会发生这样的事情:
因此,您希望在最后一步中执行的操作是通过根据.htaccess规则定义提供您自己的图像来防止图像请求达到laravel。 这样,您的网络服务器就可以更快地对丢失的图像做出响应。
答案 1 :(得分:1)
而不是检查特定路径的网址段,如果你说它只是图像。因此,如果只有具有特定扩展名的东西才需要它,您可以检查它并返回更简单的404响应:)
/* \app\Exceptions\Handler.php */
public function render($request, Exception $exception)
{
if ($exception instanceof NotFoundHttpException) {
$ext = pathinfo($request->url(), PATHINFO_EXTENSION);
if (in_array($ext, ['jpg', 'png'])) {
return response('Nope');
}
}
return parent::render($request, $exception);
}
刚刚意识到它提出了很多要求。也许是这样的,将结果缓存1分钟,这应该足够长,以便页面上的下一个404请求获取缓存而不是运行查询:)
public function boot()
{
// Sidebar
$sidebarCategories = Cache::store('file')->remember('sidebarCategories', 1, function () {
$currentCategory = $this->getCurrentCategory();
return SidebarCategory::category($currentCategory)->order()->get();
});
view()->composer('partials.sidebar', function ($view) use ($sidebarCategories) {
$view->with('sidebarCategories', $sidebarCategories);
});
// Footer
$footerColumns = Cache::store('file')->remember('footerColumns', 1, function () {
$footerLinks = FooterCategory::with('links.translations')->order()->get();
return [
1 => $footerLinks->filter(function ($value, $key) { return $value->column == 1; }),
2 => $footerLinks->filter(function ($value, $key) { return $value->column == 2; }),
3 => $footerLinks->filter(function ($value, $key) { return $value->column == 3; }),
4 => $footerLinks->filter(function ($value, $key) { return $value->column == 4; }),
];
});
view()->composer('partials.footer', function ($view) use ($footerColumns) {
$view->with([
'footerColumn1' => $footerColumns[1],
'footerColumn2' => $footerColumns[2],
'footerColumn3' => $footerColumns[3],
'footerColumn4' => $footerColumns[4],
]);
});
}
答案 2 :(得分:0)
您可以在此处使用配置来解决视图组合的多次查询运行问题。例如显示下面的代码。
公共函数compose(查看$view) {
if(!Config::has('composeVars'))
{
Config::set('composeVars') = [
'data' => User::all();
];
}
$view->with('*', Config::get('composeVars'));
}