Use Auth in AppServiceProvider - laravel

I need the ID of the user who is logged in to get a photo in the profile table, here I am trying to use View but only in the index function that gets $profile, I want all files in the view to have $profile
public function index(){
$profil = Profil_user::where('user_id',$auth)->first();
View::share('profil', $profil);
return view('user.index');
}
I have also tried AppServiceProvider but I get an error in the form of a null value if I don't log in, is there a solution to my problem?
public function boot(){
$auth = Auth::user();
dd($auth);
}

exist several way to pass a variable to all views. I explain some ways.
1. use middleware for all routes that you need to pass variable to those:
create middleware (I named it RootMiddleware)
php artisan make:middleware RootMiddleware
go to app/Http/Middleware/RootMiddleware.php and do following example code:
public function handle($request, Closure $next) {
if(auth()->check()) {
$authUser = auth()->user();
$profil = Profil_user::where('user_id',$authUser->id)->first();
view()->share([
'profil', $profil
]);
}
return $next($request);
}
then must register this middleware in app/Http/Kernel.php and put this line 'root' => RootMiddleware::class, to protected $routeMiddleware array.
then use this middleware of routes or routes group, for example:
Route::group(['middleware' => 'root'], function (){
// your routes that need to $profil, of course it can be used for all routers(because in handle function in RootMiddleware you set if
});
or set for single root:
Route::get('/profile', 'ProfileController#profile')->name('profile')->middleware('RootMiddleware');
2. other way that you pass variable to all views with view composer
go to app/Http and create Composers folder and inside it create ProfileComposer.php, inside ProfileComposer.php like this:
<?php
namespace App\Http\View\Composers;
use Illuminate\View\View;
class ProfileComposer
{
public function __construct()
{
}
public function compose(View $view)
{
$profil = Profil_user::where('user_id', auth()->id)->first();
$view->with([
'profil' => $profil
]);
}
}
now it's time create your service provider class, I named it ComposerServiceProvider
write this command in terminal : php artisan make:provider ComposerServiceProvider
after get Provider created successfully. message go to config/app.php and register your provider with put this \App\Providers\ComposerServiceProvider::class to providers array.
now go to app/Providers/ComposerServiceProvider.php and do like following:
namespace App\Providers;
use App\Http\View\Composers\ProfileComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
View::composer(
'*' , ProfileComposer::class // is better in your case use write your views that want to send $profil variable to those
);
/* for certain some view */
//View::composer(
// ['profile', 'dashboard'] , ProfileComposer::class
//);
/* for single view */
//View::composer(
// 'app.user.profile' , ProfileComposer::class
//);
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
}
}
3. is possible that without create a service provider share your variable in AppServiceProvider, go to app/Provider/AppServiceProvider.php and do as follows:
// Using class based composers...
View::composer(
'profile', 'App\Http\View\Composers\ProfileComposer'
);
// Using Closure based composers...
View::composer('dashboard', function ($view) {
//
});
I hope be useful

you can use this
view()->composer('*', function($view)
{
if (Auth::check()) {
$view->with('currentUser', Auth::user());
}else {
$view->with('currentUser', null);
}
});

Related

Laravel: how to write test for route Macro, Middleware and Model binding

I build a simple way to identify tenant with subdomain, ex: user1.example.com, and tenant will be user1. On the other hand, if user1 does not exist, the user1.example.com will response 404.
I define a Macro in service provider like following:
/**
* Register services.
*
* #return void
*/
public function register()
{
$this->app->singleton('tenancy', function (Application $app) {
return new TenancyMananger($app);
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
Route::macro('tenancy', fn (Closure $groups) => Route::domain(sprintf('{tenant}.example.com'))
->middleware(['tenancy'])
->group($groups));
Route::model('tenant', Tenant::class);
}
Then, use middleware to init and identify the tenant:
public function handle(Request $request, Closure $next)
{
Tenancy::init($request->tenant);
return $next($request);
}
And I override the getRouteKeyName method on the Tenant model to use database column other than id:
public function getRouteKeyName()
{
return 'domain';
}
Finally, I write the following feature testing case to test it:
\Illuminate\Support\Facades\Route::tenancy(function () {
\Illuminate\Support\Facades\Route::get('/test', fn () => 'hello world');
});
$tenant = Tenant::factory()->create([
'domain' => 'demo',
'name' => 'demo name',
]);
$this->get('http://demo.example.com/test')->assertStatus(200);
$this->assertEquals(Tenancy::tenant()->id, $tenant->id);
$this->assertEquals(Tenancy::domain(), $tenant->domain);
$this->assertEquals(Tenancy::name(), $tenant->name);
But I will get the error:
testing.ERROR: App\TenancyMananger::init(): Argument #1 ($tenant) must be of type App\Models\Tenant, string given
It seems like that route does not trigger the model binding so that $request->tenant int the middleware pass the string ( subdomain ) into the TenancyMananger.
Any idea what could be happening here?
Or I can not write the test like this...
Any help or guidance is much appreciated.
I use PHP 8.1, Laravel 10.x-dev and phpunit v9.5.27.
Thanks.
When you use this Tenancy::init($request->tenant); Laravel binds Model to the route. It would be best if you used something like
$tenant = $request->route('tenant');
Tenancy::init($tenant);
return $next($request);
And make sure you added Tenancy class to $routeMiddleware

Laravel Global Variable to specific views

I would like assistance with calling a global variable on Laravel app for specific pages or routes.
This is my current code which works on login
App\Providers\AppServiceProvider
public function boot()
{
view()->composer(['auth.login'], function ($view) {
$view->with('settings', AppSetting::where('id',1)->first());
});
}
This is the route for the login page
Route::get('/', function () {
return view('auth.login');
});
[Edit 1]
On the login page , I used this code bellow to get the app version
{{$settings->app_version}}
After digging a little I think a good solution might be caching your AppSetting Model.
Write the given code in App\Providers\RouteServiceProvider
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* Define your route model bindings, pattern filters, etc.
*
* #return void
*/
public function boot()
{
parent::boot();
App::before(function($request) {
App::singleton('settings', function(){
return AppSetting::where('id',1)->first();
});
// If you use this line of code then it'll be available in any view
// as $settings but you may also use app('settings') as well
View::share('settings', app('settings'));
});
}
}
App::singleton will call once AppSetting::where('id',1)->first() and after one call your settings will be cached.
And you can use {{$settings->app_version}} in your view.
Reference: stackoverflow.com/a/25190686/7047493

Laravel | Auth::user()->id isn't working in AppServiceProvider

I can get the Auth ID when i put it in any controller with
Auth::user()->id
But when i put it in AppServiceProvider.php , it returns `Trying to get property 'id' of non-object
i don't understand why ?
Eddit : I tried this but still not working
public function boot()
{
view()->composer('*', function ($view)
{
if (Auth::check())
{
$id=Auth::user()->id;
$idd=Person::where('user_id','=',$id)->get('photo');
$view->with('idd', $idd );
$view->with('id', $id );
}
});
}
Error :
Argument 1 passed to Illuminate\Database\Grammar::columnize() must be of the type array, string given, called in
To get the currently authenticated user's ID, use
Auth::id();
Another case may be that there is not a current user, in which case Auth::user() is returning NULL. Wrap the code in a
if (Auth::check())
{
// Do stuff
}
to make sure there is a user logged in.
view()->composer('*', function($view)
{$view->with('user',auth()->user());
});
it's work for me
<?php
namespace Fitness\Providers;
use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot(Request $request)
{
view()->share('user', $request->user());
}
}

Laravel add method to a vendor class

In laravel we can use with() along with redirect(), like
return redirect('home')->with(['message' => 'Some message');
I want to create some other functions like withError(), withSuccess().
How and where to create this ?
As the Laravel RedirectResponse class uses the Macroable trait, you can register response macros to do this.
Just create a new service provider say ResponseMacroServiceProvider. Register it in your app.php and register a macro in the boot method like so:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Http\RedirectResponse;
class ResponseMacroServiceProvider extends ServiceProvider
{
/**
* Register the application's response macros.
*
* #return void
*/
public function boot()
{
RedirectResponse::macro('withError', function ($value) {
return; // add logic here
});
RedirectResponse::macro('withSuccess', function ($value) {
return; // add logic here
});
}
}

Laravel 5.3 - Best way to implement Entrust role on signup?

I'm working with Laravel 5.3 and I'm trying to set a role when someone signs up, I've used the Zizaco Entrust library.
I'm unsure on the best way to achieve something like this.
I tried to do this inside RegisterController's create method like below:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
$user = User::where('email', '=', $data['email'])->first();
// role attach alias
$user->attachRole($employee);
}
But obviously that's not right. So I'm a bit unsure on what the best practice is with this sort of thing.
If, as your comment on the OP suggests, you always want to assign the same role to a registered user, you can use a Model Observer for this - it's really simple.
// app/Observers/UserObserver.php
<?php namespace App\Observers;
use App\Models\User;
use App\Models\Role; // or the namespace to the Zizaco Role class
class UserObserver {
public function created( User $user ) {
$role = Role::find( 1 ); // or any other way of getting a role
$user->attachRole( $role );
}
Then you simply register the observer in your AppServiceProvider:
// app/Providers/AppServiceProvider.php
use App\Models\User;
use App\Observers\UserObserver;
class AppServiceProvider extends Provider {
public function boot() {
User::observe( new UserObserver );
// ...
}
// ...
}
This answer is mainly based off looking at your current solution, with a dash of original question.
Rather than filling out your model with methods like createNew, you'll probably find things easier to manage if you create a type of class specifically for interacting with models. You can call this a Repository or a Service or whatever takes your fancy, but we'll run with Service.
// app/Services/UserService.php
<?php namespace App\Services;
use App\Models\User; // or wherever your User model is
class UserService {
public function __construct( User $user ) {
$this->user = $user;
}
public function create( array $attributes, $role = null ) {
$user = $this->user->create( $attributes );
if ( $role ) {
$user->attachRole( $role );
}
return $user;
}
}
Now we need to deal with the fact that we've lost the hashing of passwords:
// app/Models/User.php
class User ... {
public function setPasswordAttribute( $password ) {
$this->attributes[ 'password' ] = bcrypt( $password );
}
}
And now we have the problem of sending out an activation email - that can be solved cleanly with events. Run this in the terminal:
php artisan make:event UserHasRegistered
and it should look something like this:
// app/Events/UserHasRegistered.php
<?php namespace App\Events;
use App\Models\User;
use Illuminate\Queue\SerializesModels;
class UserHasRegistered extends Event {
use SerializesModels;
public $user;
public function __construct( User $user ) {
$this->user = $user;
}
}
Now we need a listener for the event:
php artisan make:listener SendUserWelcomeEmail
And this can be as complex as you like, here's one I'm just copy/pasting from a project I have lying around:
// app/Listeners/SendUserWelcomeEmail.php
<?php namespace App\Listeners;
use App\Events\UserHasRegistered;
use App\Services\NotificationService;
class SendUserWelcomeEmail {
protected $notificationService;
public function __construct( NotificationService $notificationService ) {
$this->notify = $notificationService;
}
public function handle( UserHasRegistered $event ) {
$this->notify
->byEmail( $event->user->email, 'Welcome to the site', 'welcome-user' )
->send();
}
}
All that remains is to tell Laravel that the Event and Listener we've just created are related, then to fire the event.
// app/Providers/EventServiceProvider.php
use App\Events\UserHasRegistered;
use App\Listeners\SendUserWelcomeEmail;
class EventServiceProvider extends ServiceProvider {
// find this array near the top, and add this in
protected $listen = [
UserHasRegistered::class => [
SendUserWelcomeEmail::class,
],
];
// ...
}
Now we just need to raise the event - see my other post about Model Observers. First off you'll need to import Event and App\Events\UserHasRegistered, then in your created method, just call Event::fire( new UserHasRegistered( $user ) ).
What I ended up doing, since I do need to do more than just one operation on the user creation is having another function for user creations.
User model
/**
* Create a new user instance after a valid registration.
*
* #param array $attributes
* #param null $role
* #param bool $send_activation_email
*
* #return User $user
*
* #internal param array $args
*/
public function createNew(array $attributes, $role = null, $send_activation_email = true)
{
$this->name = $attributes['name'];
$this->company_id = $attributes['company_id'];
$this->email = $attributes['email'];
$this->password = bcrypt($attributes['password']);
$this->save();
if (isset($role)) {
// Assigning the role to the new user
$this->attachRole($role);
}
//If the activation email flag is ok, we send the email
if ($send_activation_email) {
$this->sendAccountActivationEmail();
}
return $this;
}
and calling it like:
User Controller
$user = new User();
$user->createNew($request->all(), $request->role);
It might not be the best solution, but it does the job, and it's future prof, so if the logic on the user creation grows can be implemented aswell.

Resources