Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

dr24's avatar
Level 2

Problem with accessing global variable in Laravel application

I am trying to make a global variable in AppServiceProvider.php that I will need throught my whole application meaning in all blade files. This variable is $profile which gets the profile data from user and displays them in blades. I made it so when I am on my profile it shows authenticated user which is me and it is fine (in url is like this profile/Authuser), that Authuser is username from database. Problem is when I go to some other profile then I get error undefined username (in url profile/Someuser). I need help on to get that username in AppServiceProvider.php. Problem is in that $username in service provider. I don't know how to pass it in there globally. Any help is appreciated. Here is my code.

AppServiceProvider.php

public function boot()
{ 

    $profileId = $this->getIdFromUsername($username);  // Here is problem, I don't know how to get that username

    view()->composer('*', function ($view) {
        $view->with('profile', Auth::id() ? UserProfile::profileDetails($profileId, Auth::user()->id) : []);  
    });

    Builder::defaultStringLength(191); // Update defaultStringLength
}

public function getIdFromUsername($username)
{
    if ($user = User::where('username', $username)->first()) {
        return $user->id;  
    }
    
    return abort(404);  
}

UserProfileController.php

public function showProfile($username, Request $request)
{
    $profileId = User::getIdFromUsername($username);

    $user = User::with('userProfile')->where('id', $profileId)->first();

    $viewer = User::find(Auth::id());

    $owner = User::where('username', $username)->first();

    if($viewer->id !== $owner->id && !$owner->active){
        abort(404);
    }

    if(!$profileId){
        abort(404);
    }

    $profile = UserProfile::profileDetails($profileId, $viewer->id);

    return view('profile.show', compact('user', 'profile'));
}

UserProfile.php

public static function profileDetails($profileId, $viewerId)
{
    $profile = static::profileData($profileId, $viewerId);

    if ($profile) {
        if ($viewerId != $profileId) {
            # Viewer is displaying another user's profile.
            $myProfile = false;
            } else {
            $myProfile = true;
            }
        }

        $profile = [
            'viewerId' => $viewerId,
             'profile_id' => $profileId,
             'myProfile' => $myProfile,
        ];

    return $profile;
    }

web.php

Route::get('profile/{profile}', 'UserProfileController@showProfile')->name('profile.show');
0 likes
7 replies
frankincredible's avatar

Is this the logged in user? If so, this is not the route I'd be going down... just reference auth()->user()->id where needed.

dr24's avatar
Level 2

@frankincredible

Well no. I am auth user and I need to view someone elses profile. I need to pass $username in URL from boot method in AppServiceProvider.php or something similar that will work

frankincredible's avatar

Gotcha. If you are passing it via the URL, let's say as ?username=frankincredible, But you want it accessible on every request, what I would do is add it to a Middleware, then wrap your routes in the middleware.

Just be a little careful with this. You're introducing a SQL query in getIdFromUsername on every single pageload, that you probably don't want/need.

Within your middleware, you could do something like add the $profileId to the session with something like:

session(['profileId' => User::where('username', request('username'))->first()->id ?? null]);

And then perhaps wrap that in an if (session()->has('profileId') == false) so you're only over-writing it (and adding the SQL query to find it) when it doesn't already exist in the session.

You could also write a function to remove it from the session... I'm assuming you're using this for something like an "impersonate user" feature for an admin? Then you can add an "End Impersonation" button that would hit a route that has session()->forget('profileId');

1 like
dr24's avatar
Level 2

@frankincredible

Hi, can you please tell me more precise with an example or piece of code how to implement this middleware to work? I am trying but I just can't seem to make it work. Also I get username from URL but not from request, but from database column 'username' in users table

frankincredible's avatar
Level 14

To create a new middleware, use the make:middleware Artisan command:

php artisan make:middleware ImpersonateUser

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // If the request does not say which username to get, it's not trying to impersonate
        if (request('username')) {
            return $next($request);
        }

        // Otherwise, set the impersonated User if the request contains "impersonate_username".
        // Only set this if it isn't already in the session.
        if (
             (session()->has('impersonatedUser') == false) 
             && (request('impersonate_username'))
         ) {
             session(['impersonatedUser' => User::where('username', request('impersonate_username'))->first()]);
         }

        // Go to the next request.
        return $next($request);
    }
}

Register the middleware in your $routeMiddleware. See: https://laravel.com/docs/7.x/middleware#assigning-middleware-to-routes

In your routes file (presumably web.php):

Route::group(['middleware' => 'impersonate'], function ($app) {
        // ------------------------ YOUR ROUTES GO HERE ------------------------ //
});    

I'm not sure what you mean when you say the username comes from the database. I understand you store a user in the database, but your application must somehow be told which username to use. That's going to come from a limited number of places. Being sent in a request (usually in an /impersonate?impersonate_username=crashoveride, but I suppose you could also hard-code it into a config file if it's only ever going to be one username.)

For what it's worth, I think I'd place a

STORE /impersonate/{user}

where {user} was a userId to impersonate. It would be wrapped in auth middleware and also abort_if the logged in user doesn't have the authority to impersonate the given user.

I'd also add a

DELETE /impersonate

That simply removes the impersonatedUser from the session.

1 like
Oussama's avatar

So I was looking for a way to define a variable globally in Laravel, but I couldn't find a perfect or clean solution.

So I'm writing this question to help my fellow developers who will have the same problem in the future :D.

To simplify the explanation, let's take an example. Let's assume that we need an instance of the Model Client to be accessed in all controllers and views, and this client should be always retrieved by the currently authenticated User. So each time we need to get our Client: we should get it through the following call :

Auth::user()->client // I don' like it :)

Suggested Solution :

First: Let's create a middleware and name it :

<?php

namespace App\Http\Middleware;

use App\Exceptions\ClientNotFoundException;
use App\Models\Client;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;

class CheckForClient
{
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $client = Client::getByUser(Auth::user());

        if ($client) {
            App::singleton(Client::class, static function () use ($client) {
                return $client;
            });

            View::composer('*', static function ($view) use ($client) {
                $view->with('client', $client);
            });
        } else {
            throw new ClientNotFoundException('Client not found!');
        }

        return $next($request);
    }
}

Second: Now we need to add our middleware to kernel.php (App\Http\Kernel) so that it will be executed on every request from our application. This way, we will always have the current client for the currently authenticated user. And While we have used Auth::user() inside our middleware, we have to run it after the web middleware that is responsible for booting up the session.

Helpful link: https://laracasts.com/discuss/channels/laravel/how-can-i-access-the-authuser-in-a-middleware-class, and special thanks to @thomaskim for his very helpful reply.

/**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            EncryptCookies::class,
            AddQueuedCookiesToResponse::class,
            StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            ShareErrorsFromSession::class,
            VerifyCsrfToken::class,
            SubstituteBindings::class,
            CheckForClient::class,  // THIS IS OUR MIDDLEWARE
        ],

        'api' => [
            'throttle:api',
            SubstituteBindings::class,
        ],
    ];

Finally: We can call our Client now from any Controller, using:

/** @var Client $client */
$client = app(Client::Class);
if (!$client instanceof Client) {
    return false;
}

Please or to participate in this conversation.