I've code in my controller which returns some $data, and I want to refer that in all my blades, I can make routes for each page, but I don't like this way. I thought should be better if I refer this $data on layout.blade which include navbar, and etc..., but is it a possible to make route without url? cause I don't want to appear my layout.blade, So my question is, what is a best way to get $data on each blade?
You may perhaps want a view composer. A view composer is an extension of a blade via php that runs before the blade.
In app service provider you set the view you want to view composer class.
use Illuminate\Support\Facades\View;
use App\Http\ViewComposers\LayoutComposer;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
View::composer('layout', LayoutComposer::class);
}
}
Then write your logic in the class.
use Illuminate\View\View;
class LayoutComposer
{
public function compose(View $view)
{
$data = Model::where('id',###)->first();
return $view->with(['data' => $data]);
}
}
https://laravel.com/docs/7.x/views#view-composers
Related
I am new to laravel and need help. After login user, on the dashboard page I have partial sidebar blade template that shows the user's balance data that load from database. This must be loaded for every dashboard pages.
I can not imagine how to create a controller for this user' balance since every pages have their own routes and controller.
public function getBalance()
{
$userbalance = \App\UsersBalance::where('userid', '=', Auth::user()->id)->first();
$balance = $userbalance->balance;
return view(......);
}
Kenny's answer is good if you want to share the data with all pages. However, if you only want to share with user dashboard pages and not the entire website, you probably want to use view composers.
https://laravel.com/docs/5.8/views#view-composers
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
// limit returning the balance to only your dashboard layout
view()->composer([
'layouts.dashboard'
], function($view) {
$userbalance = \App\UsersBalance::where('userid', '=', Auth::user()->id)->first();
view()->share('balance', $userbalance->balance);
});
}
}
This will pass the $balance variable to all pages that extend layouts.dashboard. You can change this layout name as necessary, or even add additional layouts since the view composer accepts an array.
You could share data with all your views. From the docs:
Sharing Data With All Views
Occasionally, you may need to share a piece of data with all views
that are rendered by your application. You may do so using the view
facade's share method. Typically, you should place calls to share
within a service provider's boot method. You are free to add them to
the AppServiceProvider or generate a separate service provider to
house them (...)
So, you could make your query there and then pass it to every view:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\View;
class AppServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
$loggedInUser = auth()->user();
View::share('loggedInUser', $loggedInUser);
}
}
So even tough your controller doesn't return this value:
# MyController.php
public funcion myFunction()
{
return view('my_view');
}
You could access the properties defined globally:
# my_view.blade.php
<span>{{ $loggedInUser->name }}</span>
Heey guys! I use Laravel 5.4, WAMP for localhost. I am struggling with the problem to call a Controller#methodName within my header.blade.php file, because I want to show in my header.blade.php file all notifications for the User. Normally I was getting all needed data with the help of routes in different pages. But for this case I need to call without using routes. Here is my code for my NotificationController:
class NotificationController extends Controller
{
public function getNotification(){
$notifications = Notification::where('user_id',Auth::user()->id)->get();
$unread=0;
foreach($notifications as $notify){
if($notify->seen==0)$unread++;
}
return ['notifications'=>$notifications, 'unread'=>$unread];
}
}
And I should receive all these data in my header file. I have used: {{App::make("NotificationController")->getNotification()}}
and {{NotificationController::getNotification() }} But it says Class NotificationController does not exist. Please heelp!
Instead of calling the controller method to get notifications, you can make a relationship method in your User model to retrieve all the notifications that belongs to the user and can use Auth::user()->notifications. For example:
// In User Model
public function notifications()
{
// Import Notification Model at the top, i.e:
// use App\Notification;
return $this->hasMany(Notification::class)
}
In your view you can now use something like this:
#foreach(auth()->user()->notifications as $notification)
// ...
#endforeach
Regarding your current problem, you need to use fully qualified namespace to make the controller instance, for example:
app(App\Http\Controllers\NotificationController::class)->getNotification()
Try using the full namespace:
For instance, App\Http\Controllers\NotificationController::getNotification
but of course, controllers aren't meant to be called the way you're using them. They're meant for routes. The better solution is to add a relationship in your user model like so:
public function notifications()
{
return $this->hasMany(Notification::class)
}
And then use this in your view like so:
#foreach(Auth::user()->notifications as $notification)
I have a few things that I want to present on every page, like $gameAccounts = Auth::user()->gameAccounts()->get();
What would be the best approach to present this variable globally, on each page?
If you need it only for the views you can use a view composer in your AppServiceProvider
public function boot()
{
View::composer('layouts.base', function ($view) {
$view->with('gameAccounts', Auth::user()->gameAccounts);
});
}
If you need it globally you can store it in a config also in AppServiceProvider.
For shared functionality I would recommend to write a trait. The trait can be used throughout your controllers and provide the same functionality for all.
Example:
trait GameSettingsTrait
{
public function getUserGameAccounts()
{
return Auth::user()->gameAccounts()->get();
}
}
In your controller do:
class IndexController extends Controller
{
use GameSettingsTrait;
...
Another approach would be to put the logic in the base controller in app/Http/Controllers/Controller.php. Btw, there you can see that it already uses traits for other functionality.
You need to use view composer.
Look at the doc.
https://laravel.com/docs/5.2/views#view-composers
Use view composer is a best way to do this.
Just add this rows to your AppServiceProvider.php inside boot method:
public function boot()
{
//
view()->composer('*', function ($view) {
$view->with('user', Auth::user()->gameAccounts()->get());
});
}
I need to share the currently logged in user to all views. I am attempting to use the view->share() method within AppServiceProvider.php file.
I have the following:
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Auth\Guard;
class AppServiceProvider extends ServiceProvider {
public function boot(Guard $guard)
{
view()->share('guard', $guard);
view()->share('user', $guard->user());
}
//..
}
However, when I hit up a view (after logging in), the user variable is null. Strangely, the $guard->user (the protected attribute, not the public method user()) is not. The output I get is the following:
Note the guard->user variable is populated, but the user variable is null.
Better off using View Composers for this one.
In your ComposerServiceProvider in boot():
view()->composer('*', 'App\Http\ViewComposers\GlobalComposer');
In HTTP/ViewComposers create a class GlobalComposer, and create the function:
public function compose( View $view )
{
$view->with('authUser', Auth::user());
}
http://laravel.com/docs/5.0/views#view-composers
You can solve this problem without creating a file.
Add these codes to boot() action of your ServiceProvider and that's it.
view()->composer('*', function($view){
$view->with('user', Auth::user());
});
Source also same: http://laravel.com/docs/5.0/views#view-composers
Look Wildcard View Composers.
I've created a very basic app in Laravel 4, it's something I'll be reusing a lot in various projects so it made sense to convert it to a package before i got too far, but I'm struggling to make the changes to get it working, which I think is largely due to figuring out how to access the various objects that are normally available in an app, eg View::make
I had the following code working in an app:
class PageController extends BaseController {
public function showPage($id)
{
//do stuff
return View::make('page/showPage')
->with('id', $id)
->with('page', $page);
}
for the package I have the following:
use Illuminate\Routing\Controllers\Controller;
use Illuminate\Support\Facades\View;
class PageController extends Controller {
public function showPage($id)
{
//do stuff
return View::make('page/showPage')
->with('id', $id)
->with('page', $page);
}
However this does not load the blade template which is located at:
workbench/packagenamespace/package/src/views/page/showPage.blade.php
nor does this work:
return View::make('packagenamespace/package/src/page/showPage')
Also, I am wondering if what i have done with the use statements where I use the facade object correct, to me it seems like there should be a neater way to access things like the View object?
You should read the docs: http://four.laravel.com/docs/packages
Specifically the part explaining loading views from packages ;)
return View::make('package::view.name');
If you don' want to use:
use Illuminate\Support\Facades\View;
Just do:
use View;
Or even without the use statement:
\View::make('package::view.name');
// Serviceprovider.php
$this->loadViewsFrom(__DIR__.'/resources/views', 'laratour');
// Controller
<?php
namespace Mprince\Laratour\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class LaratourController extends Controller
{
public function index()
{
return view('laratour::index');
// return view('packageName::bladeFile');
}
//END
}