Laravel 5.2 composer viewed several times

I had some (main) performance problems in the project that I am working on, and after registering all the requests that are being executed, I realized that many of them are being executed several times, and I cannot get to the root of the problem.

All requests that are executed multiple times belong to my composer supplier.

This is what my composer looks like:

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')); }); } 

Both of these queries (Sidbar and Footer categories) are executed approximately 6 times, although each of them is called exactly once. Both of them are invoked in the main view using @include ('partialname').

I tried this:

 if($view->offsetExists('sidebarCategory')) return; 

But offsetExists always returns false (even after calling it for 5. time).

Any idea why this is happening and what am I doing wrong?

Edit:

I understood where the problem is. On the page I visit (when these few requests are executed), there are about 404 elements (images mostly). Every time a file is not found, a new 404 exception is thrown. And every time a 404 exception is thrown, a 404 scan => is done the same as the footer / sidebar requests (since they are part of the 404 view). Example: http://imgur.com/a/RrmOD

So, the question is how to prevent the visualization of the view when it is not necessary (for example, 404 is an image that was not found).

Here is a snippet of code from my routes, which I believe is the reason this happens:

 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: I know that this piece of code is extremely non-optimized (since it basically executes the same query twice, once, to see if the element exists, at another time, actually in the controller). This is a work in progress, and it is on the task list.

Edit 2:

I came up with the following solution, I am open to improvements, as this is a somewhat hacky way (if I add more folders, I will also need to remember this). I have only 3 direct subfolders in the shared folder: something, files and resources.

The solution is to check the first segment of the URL when rendering the exception (in the app / Exceptions / Handler.php file) and return a 404 response without presentation if it matches one of three folders:

 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); } 

Thanks in advance

+8
php laravel laravel-5
source share
2 answers

Do not redirect file requests through laravel and submit a blank image to 404

.htaccess sample:

 RewriteEngine On RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png|ico)$ [NC] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule .*$ /no_picture.png [L] 

You would place it above the rules that redirect to index.php

It is assumed that the images are served from a website, and not by streaming the contents of the database.

Basically the following happens:

  • User backend upload image:
  • laravel stores the image in / some / path / to / store / data / public / 12a / 4d8 / 458 / 12a4d8458.gif
  • laravel stores image as 12a4d8458.gif in your database
  • -------------------- time passes by ------------------------
  • Visitor request page.
  • The request does not match the file. redirect to index.php (according to .htaccess)
  • the request is sent to index.php
  • laravel creates the page. Finds an image
  • laravel composes a complete public url.
  • www.awesome.com/data/public/12a/4d8/458/12a4d8458.gif
  • html composite content hits the visitor
  • ---------------- Millisecond pass ------------------------
  • the visitor asks for image / data / public / 12a / 4d8 / 458 / 12a4d8458.gif
  • the request matches the file of the file served by apache
  • laravel remains blissfully unaware of the request
  • ----------------- not a millisecond has passed -------------
  • Visitor requests image / data / public / 4e8 / d44 / 98f / 4e8d4498f.gif
  • The request does not match the file. redirect to index.php (according to .htaccess)
  • laravel creates the page. does not find the route.
  • laravel calls 404 procedures
  • laravel creates a 404 page with all associated triggers
  • laravel serves 404 user

So what you want to do in the last step is to prevent the image request even before laravel, showing your own image in accordance with the .htaccess rules. Thus, your web server can respond more quickly to a missing image.

+5
source share

Check file extension

Instead of checking URL segments for specific paths, and if you say that these will be just images. Therefore, if it is needed only for things with specific extensions, you can check this and return a simpler 404 answer for those :)

 /* \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); } 

Caching

I just realized that he was making a lot of requests. Perhaps something like this, cache the results for 1 minute, it should be long enough so that the next 404 requests on the page take the cache instead of launching requests :)

 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], ]); }); } 
+1
source share

All Articles