How to prevent loops in laravel global variable - laravel

I've created file GlobalVariable.php inside app\Composers
public function compose($view)
{
$categories = \App\Models\Category::all();
$view->with('globCategory', $categories);
}
then register to AppServiceProvider the code view()->composer('*', GlobalVariable::class);
I use global $globCategory for creating dynamic navbar
<ul class="nav nav-tabs border-0 flex-column flex-lg-row">
#foreach ($globCategory as $item)
<li class="nav-item">
{{$item->name}}
</li>
#endforeach
</ul>
the only problem here when I see laravel debuggar it show repetition of categories query.
here is the result
How to avoid this looping query? is there correct way?

The way you're registering your view composer (using '*' instead of a particular view name), it's going to call the compose method for every single rendered view + subview.
What you can do is instead of this:
view()->composer('*', GlobalVariable::class);
Have this:
\View::share('globCategory', \App\Models\Category::all());
This will globally share your categories (within views), and run the query only once.

View composers, as described from the laravel documentation, bind data to a view every time it is rendered. They clean our code by getting fetching data once and passing it to the view.
While it is possible to get the data in every controller method and pass it to the single view, this approach may be undesirable.
Replace the view name with an asterisk wildcard.

Related

how to display data based on specific id in laravel?

I am new to laravel. I want to send data as id of existing data. Id comes from products.blade I send via href tag as shown below to gallery page. I have tried to find a way through other sites but it still doesn't work
<a class="btn btn-success" href="/dashboard/galleries/{{ $product->id }}"><i class="ri-image-add-line text-white"></i></a>
then i create a route like this
Route::resource('/dashboard/galleries', DashboardGalleryController::class)->middleware('admin')->shallow();
in the controller gallery, I made like this
public function index($id)
{
$gallery = Gallery::where('products_id', $id)->get();
return view('dashboard.galleries.index', compact('gallery'));
}
then inside the gallery page, I want to display a table to add images based on that id.
dashboard/galleries/index.blade.php
<h1>{{ $gallery->id }}</h1>
should i add data inside foreach or outside?
A restful resource controller sets up some default routes for you and even names them.
and ur case the logic should be inside show() function not index()
check this issue it will help u same issue solved here

Laravel 5.6 dynamic pages from a database best practice

I am using/learning Laravel 5.6 and wondered if this is the best approach in trying to accomplish dynamic pages from a database.
The approach I have taken works but I feel it could be improved especially with having to retrieve the pages for the navigation bar with every request.
I have a route in web.php
Route::get('/', 'PageController#index')->name('index');
Route::get('/{page}', 'PageController#show');
I then have my page controller with index and show functions.
public function index()
{
$pages = Page::all();
$posts = Post::latest('created_at')->paginate(2);
return view('index', compact('posts','pages'));
}
public function show($uri)
{
$pages = Page::all();
$page = Page::where('uri', $uri)->first();
return view('templates.page', compact('page','pages'));
}
Now in my header.blade.php I display the list of pages like this:
#foreach($pages as $page)
<li class="nav-item">
<a class="nav-link" href="/{{ $page->uri }}">{{ $page->title }}</a>
</li>
#endforeach
Now my problem is with all the other controllers I have to get the page's information from the database everytime which seems inefficient.
Any advice would be appreciated. Thank you in advance.
You can share your pages data with every view automatically by adding View::share('key', 'value');in the boot method of a service provider. Alternatively you can create a view composer.
one layout blade.
yield title by
<title>#yield('page-title')</title>
then on view,
//process title using php from DB
then display using
#section('page-title')
{{$page_title}}
#endsection

laravel 5.5 multiple controller inside one view

How to show TeamController#index and ProductController#index both show list of team and product inside one view main.blade.php
Looks like you want to show two datasets on one page. Basically, it means you have to execute two controller methods but it's not necessary to follow each and everything that official documentation says.
For example, if Products belong to a team, you can execute only TeamController#index and show products as given below.
#foreach($teams as $team)
#foreach($team->products as $product)
{{ $product->name }}
#endforeach
#endforeach
If no teams and products are two different entities and does not have any relation, you can just pass teams and products like this:
TeamController.php
public function index()
{
$teams = Team::all();
$products = Product::all(); // Don't forget to include 'use App\Product'
return view('index',compact(['teams','products']);
}
and then you can show teams and products like this:
index.blade.php
#foreach($teams as $team)
{{ $team->name }}
#endforeach
#foreach($products as $product)
{{ $product->name }}
#endforeach
Getting information from two different models does not mean you have to execute two different controller functions.
Still, if you want to get data from two different controllers, you can setup index.blade.php and create two ajax requests that will get data from two different URLs (two different controller methods).
Let me know if you have any more questions.
You can't show results from two controllers like that. Create a view that includes both the view that TeamController#index and ProductController#index return. be aware that both might be extending a layout which will probably try to load your page twice, so keep in mind to split the views into smaller components and include only those.
More info here
https://laravel.com/docs/5.6/views#creating-views

Notification not working on Multiple guards

I have 2 guards. One 'user' and the other 'admin'.
I have stored notification in database as admin. But guard('admin') is not working.
Here is my code in blade file:
<span class="badge badge-light">{{count(auth()->guard('admin')->user()->unreadNotifications())}}</span>
But i am only getting '1' as a result. I have 6 records in my table. Also my forech loop is not working either with guard. Here is the code:
<ul class="dropdown-menu">
#foreach(auth()->guard('admin')->user()->notifications() as $notifications)
<li>{{$notifications->type}}</li>
#endforeach
</ul>
Thanks a bunch
Try using notifications and unreadNotifications without ()
auth()->guard('admin')->user()->notifications
//
auth()->guard('admin')->user()->unreadNotifications
When using () on relationships you are always retrieving a Eloquent or Query Builder instance

Laravel 4 - understanding View::share()

From what I understand:
View::share('foo','bar');
Will make $foo available in all views.
However, is it correct to say View::share() can be used only in the __construct()?
Because from outside __construct() I can't make it to work.
View::share should be available anywhere within your application. A common place that it is used is in view composers, but it should be usable within a route or wherever you need it.
Yes, adding:
View::share('foo','bar');
in your routes.php file will make $foo (with a value of 'bar') available in all views. This is especially useful for something like Twitter Bootstrap's "active" navigation classes. For example, you could do:
View::share('navactive', '');
to make sure the navactive variable is set in all views (and thus won't throw errors) and then when you are making views (in your controller, for example), you could pass:
return View::make('one')->with('navactive', 'one');
and then in your view (preferably some bootstrappy blade template) you can do the following:
<ul class="nav">
#if ( Auth::user() )
<li #if ($navactive === 'one') class="active" #endif>One</li>
<li #if ($navactive === 'three') class="active" #endif>Three</li>
<li #if ($navactive === 'five') class="active" #endif>Five</li>
#endif
</ul>
Basically if you want to share the variables through all view, you might first want to create a base route(E.x.:internalController.php) as a parent class then extend other controllers as a child of it(E.x:childController.php).
And yeah you will most likely set the view::share('foo', $bar) in the __constructor() of the internalController.php, since it lunches whenever the class is initialized, this way the parent class will serve the variable values to the child classes.

Resources