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.
Related
I am working on a Laravel control panel project where we should be able to toggle from one site to another and get the detail of the site based on the ID passed in the route.
In itself this is quiet easy to do but as I will have several controllers using this technique it means for each controller and each controller instance I will have collect the site instance and it does not look very user friendly due to the many repetitions.
Here is what I have:
Route:
Route::get(
'cp/site/{website}/modules/feeds',
'App\Http\Controllers\Modules_sites\Feeds\FeedController#index'
)->name('module_site.feeds.index');
Model:
class Website extends Model
{
use HasFactory;
protected $primaryKey ='site_id';
}
The database is simple with an id (site_id) and name
Controller:
public function index(Website $website)
{
dd($website -> name);
}
The above is working fine but I am going to end with dozens of methods across multiple controllers doing the same thing, and what if changes are required.
I have looked at the ID of using the AppServiceProvider to create the Website instance and then pass it to the controllers and views but I can't do this as the route is not defined at this stage and I only seem to be able to pass this to the view.
Essentially, I am looking to create something similar to the auth()->user() method that is available from controllers and routes without the needs to pass it to each controller.
Is this possible?
Perhaps you could use middleware to set this value? Something like this to put it in the session globally:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class CheckWebsite
{
public function handle(Request $request, Closure $next): mixed
{
$request->session()->put("website", $request->route("website"));
return $next($request);
}
}
Or this on a per-controller basis:
<?php
namespace App\Http\Controllers\Modules_sites\Feeds;
use App\Http\Controllers\Controller;
use Closure;
use Illuminate\Http\Request;
class FeedController extends Controller
{
public function __construct()
{
$this->middleware(function (Request $request, Closure $next) {
$this->website = $request->route("website");
return $next($request);
});
}
public function index()
{
dd($this->website->name);
}
}
Also worth mentioning that routes are not defined like that in Laravel 8 any longer. It should look like this:
Route::get(
'cp/site/{website}/modules/feeds',
[FeedController::class, 'index']
)->name('module_site.feeds.index');
With an appropriate import for the controller class.
as you primary key is not id so it will not work automatically you need to tell laravel to search by column name
code will be
Route::get('cp/site/{website:site_id}/modules/feeds', 'App\Http\Controllers\Modules_sites\Feeds\FeedController#index')->name('module_site.feeds.index');
you need to use {website:site_id}
ref link https://laravel.com/docs/8.x/routing#customizing-the-default-key-name
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
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>
I've created a helper file in App folder named as Helper.php.
app/Helper.php
<?php
namespace App;
use Illuminate\Support\Facades\DB;
class Helper {
public function get_username($user_id)
{
$user = DB::table('users')->where('userid', $user_id)->first();
return (isset($user->username) ? $user->username : '');
}
}
app/Providers/HelperServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class HelperServiceProvider extends ServiceProvider
{
public function boot()
{
//
}
public function register()
{
require_once app_path() . 'Helper.php';
}
}
config/app.php
Inside the provider's array...
App\Providers\HelperServiceProvider::class,
Inside aliases array...
'Helper' => App\Helper::class,
Everything was working fine but now I have the following error.
ErrorException thrown with message "Non-static method Helper::get_username($user->id) should not be called statically
But when I add static keyword to function its works fine. What's the difference between static and non-static methods?
Aliases give you the possibility to access a facade in a blade template without adding it in the template (vie use statement). When calling a method via a facade, you call this method statically and the facade will call the object of the class containing this method.
In Laravel, it is usually more convenient to create a file containing helpers like Laravel does and to autoload that file via composer.
Please check here for more details
I have a class called CustomerController with a delete function:
class CustomerController extends Controller
{
public function getAllCustomer()
{
return \App\model\Customer::get();
}
public function destroy (Customer $id)
{
$id->delete();
}
This is the route:
Route::delete('customer/{id}' , 'CustomerController#destroy');
I get this error:
Class App\Http\Controllers\Customer does not exist
I already tried Composer update and Composer dump-autoload with no success.
A screenshot:
Thank you very much!
When you do not include classes using use statements, php will try to find the class in the current namespace.
So, the function function destroy (Customer $id) will look for the class Customer in the App\Http\Controllers namespace. To avoid this, add a use statement for the App\model\Customer class above on top of your controller class. For example:
<?php
namespace App\Http\Controllers;
use App\model\Customer;
class CustomerController extends Controller
{
public function getAllCustomer()
{
return Customer::get();
}
public function destroy (Customer $id)
{
$id->delete();
}
}
Now you can also use a shorter name in the getAllCustomer() function.
Change this :
return \App\model\Customer::get();
to this:
add namespace at the top:
use App\Customer;
return Customer::get();
as you are using route model binding on delete action by injecting Customer class to the method therfore its failing so make sure you add model namespace at the top of the file(CustomerController).
The error is happening beacuse CustomerController is trying to look for Customer model in controllers namespace which means that your model namespace is wrong.