Laravel-debugbar: Debugbar::enable() does not seem to work!

Created on 23 Nov 2015  ·  29Comments  ·  Source: barryvdh/laravel-debugbar

I have the below code in a middleware and disabling debug_bar (if i have it enabled by default) works fine! However if I try the opposite, meaning having the debug bar disabled by default and try to enable it on demand then id does not work.

Any ideas?

P.S. lavavel's own debug mode works fine like this! gets enable or disabled when i want!

    if ($request->has('disable_debug')) {
        \Config::set('app.debug', false);
        \Debugbar::disable();
    }
    if ($request->has('enable_debug')) {
        \Config::set('app.debug', true);
        \Debugbar::enable();
    }
stale

Most helpful comment

I have a use case where none of these solutions seem to work:

This is what I ended up doing:

  1. Create middleware: /app/Http/Middleware/DebugBar.php:
<?php namespace App\Http\Middleware;

use Closure;

class DebugBar
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        app('debugbar')->disable();

        if (auth()->check() && auth()->user()->is_admin) {
            app('debugbar')->enable();
        }

        return $next($request);
    }
}
  1. Add this new middleware to /app/Http/Kernel.php as the last item in the web middleware group.
  2. Important to note here is that the enabled value needs to be null in /config/debugbar.php.
    Note: I think this still has the issue of the various libraries being loaded on each request, adding a bit of overhead.
  3. Don't forget to add the appropriate getIsAdminAttribute() method to your user model, if that's your criteria for enabling debugbar.

To use debugbar in production, you will need to set APP_DEBUG env variable to true while debugging things.

All 29 comments

i have the same issue

I have found a workaround however I would prefer to do it with middleware!

I figured that in config/laravel debugbar.php I can do something like

      'enabled' => function(){
      if (Illuminate\Support\Facades\Request::has('enable_debug')) { 
          return true; 
      } 
      return config('app.debug');
      }

my problem is that only admins should be able to see it, so there's no way enabeling that during boot, i eventually picked the option to enable it for all, the in middleware disabeling it for users, but i would love to see a real fix for the issue so it can work as described

maybe you should have a logged in admin leave a season variable once they login so in the config you can check for that. it will work on the second page load i suppose but it could be close to what you are after. i thought of enabling via permissions in the admin as well but since i will only need to see debugbar in a production site when something is wrong i figured that enabling it via a passphrase stored in a session might be the quickest way to go about it!

btw if you are enabling debug for all your users on a production site and then hiding it selectively you are getting a major performance hit since debugbar gathers all the info it needs but simply hiding itself!

same issue here.

I have the same issue here, and here's my way to reillustrate:

  1. open config/debugbar.php setting storage driver to redis
  2. run php artisan config:cache
  3. refresh browser and that cute icon is gone.

But if I ran php artisan config:clear instead of php artisan config:cache , it'll show up again. So I guess it's maybe a integration bug with L5.1's new feature(Config Caching)?

any news here? still waiting for a fix. @barryvdh Can I be any help in fixing? I need some hints.

Not really sure, the problem is probably that the assets are in a different route, so they won't be correctly rendered if you enable them on certain routes only.

I would probably try to use a callback function in the config, or enable the debugbar conditionally in your service provider.

409

Is how I fixed this issue

Happens to me too

Changing the debugbar config using a Closure works fine.

@barryvdh Even the callback solutions stopped working after version 2.2.2:

'enabled' => function(){
        return Cookie::get('debugbar') || config('app.debug');
    },

Works fine in 2.2.0

To get the callback version working in 5.2.2+ I used the env callback.

'enabled' => env('DOINK', function() { return config('app.debug'); }),

I have a use case where none of these solutions seem to work:

This is what I ended up doing:

  1. Create middleware: /app/Http/Middleware/DebugBar.php:
<?php namespace App\Http\Middleware;

use Closure;

class DebugBar
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        app('debugbar')->disable();

        if (auth()->check() && auth()->user()->is_admin) {
            app('debugbar')->enable();
        }

        return $next($request);
    }
}
  1. Add this new middleware to /app/Http/Kernel.php as the last item in the web middleware group.
  2. Important to note here is that the enabled value needs to be null in /config/debugbar.php.
    Note: I think this still has the issue of the various libraries being loaded on each request, adding a bit of overhead.
  3. Don't forget to add the appropriate getIsAdminAttribute() method to your user model, if that's your criteria for enabling debugbar.

To use debugbar in production, you will need to set APP_DEBUG env variable to true while debugging things.

One problem with enabling it conditionally in a service provider is that service providers are booted before all middlewares. This means we cannot use a session variable to determine if the debugbar should be enabled or not. Neither can we check if the user is authenticated. Two functions that are implemented by middlewares.

For 5.3 I have override authenticated($user) method in LoginController

protected function authenticated($user)
    {
        if (\Entrust::hasRole('admin')) {
            \Log::alert('Debugger Enabled');
             \Debugbar::enable();
        } else {
            \Log::alert('Debugger Disabled');
            \Debugbar::disable();
        }
    }

@mikebronner

To use debugbar in production, you will need to set APP_DEBUG env variable to true while debugging things.

How to set APP_DEBUG=true on production only for admin?

@GoodJob You set that to true only while debugging. Additionally you will need to add a flag to the user model that lets you determine if the user is an admin.

Add something dirty to your App\User model, like so:

public function getIsAdminAttribute() : bool
{
    return $this->id === <your user ID here>;
}

Should suffice for rough and tumble debugging on a case by case basis. Even better if you can determine who has admin rights by a flag in the database.

@mikebronner

To use debugbar in production, you will need to set APP_DEBUG env variable to true while debugging things.

Sorry, but where should I set APP_DEBUG=true? In .env file on production? Then everyone on errors will see debug error pages :(

I can't make it work in any other way then set APP_DEBUG=true in .env, but I can't set it there, because I'm debugging app all day long on production :)

P.S. Got some answers on how to set APP_DEBUG=true on production, so debugbar will turn on also: https://stackoverflow.com/questions/45159504/debug-laravel-on-production-for-admin

We wanted to enable Debugbar in production and have the following features:

  • Controlled through a cookie, so that admins can toggle Debugbar and then log out to use it as a guest or any other user
  • Config caching should work
  • Route caching should work

Achieving this requires you to jump through a few hoops. You can not just set the APP_DEBUG environment variable because the env helper should only be used in config files when using config caching. Additionally, Debugbar requires a few routes that they add by hooking into the routing engine, which means Debugbar must be enabled when run through CLI.

0. Base config

We have Debugbar disabled by default in config/debugbar.php:

'enabled' => false,

1. Adding policy method

Who should be allowed to toggle Debugbar? Add a policy method for that. Here we chose to add it to our UserPolicy:

public function enableDebugbar(User $user, User $target) {
    return $target->isSuperAdmin();
}

2. Setting the cookie

This one is easy. Add the following route:

public function toggleDebugbar(Request $r) {
    $this->authorize('enableDebugbar', $user); // Check with UserPolicy if you are authorized to do this
    $is = $r->cookie('debugbar_enabled', false);
    if (!$is) {
        $code = Hash::make(implode(':', [
            config('app.key'), // This is secret, so that nobody else can fake this cookie
            date('Ymd'), // Force the cookie to expire tomorrow
            $r->server('REMOTE_ADDR'), // Cookie only valid for current IP
        ]));
        return redirect()->back()->withCookie(
            'debugbar_enabled', $code, 1440
        );
    } else {
        return redirect()->back()->withCookie('debugbar_enabled', null);
    }
}

This cookie must not be encrypted. The reason is that we want to read the cookie before any middlewares later (to enable Debugbar as early as possible). Open app/Http/Middleware/EncryptCookies.php and add the cookie to the $except array:

protected $except = [
    'debugbar_enabled',
];

3. Enabling Debugbar when you have the cookie

We enable Debugbar in AppServiceProvider. For us this is early enough. Add this boot() method to your AppServiceProvider:

function boot(Request $r) {
    // Enable Debugbar if special hashed cookie is set
    $cookie = $r->cookie('debugbar_enabled', false);
    $enabled = false;
    if ($cookie !== false) {
        $matches = Hash::check(implode(':', [
            config('app.key'),
            date('Ymd'),
            $r->server('REMOTE_ADDR'),
        ]), $cookie);

        if ($matches) {
            $enabled = true;
        }
    }

    if ($enabled) {
        $this->app['config']->set('debugbar.enabled', true);
    } else {
        // We have the querylog enabled so that Debugbar can collect data.
        // Disable when we don't need Debugbar
        if (config('app.environment') === 'production') {
            DB::connection()->disableQueryLog();
        }
    }
}

4. Caching Debugbar routes

To cache Debugbar routes we need to make sure it is enabled during route compilation. Debugbar is disabled in production, but we force it to be enabled in Artisan. Add this method to app/Console/Kernel.php:

// Ugly hack to cache Debugbar routes. Always enable Debugbar in
// Console mode. All it does in console mode is to register its
// routes.
public function bootstrap() {
    if (isset($_SERVER['argv']) && isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] === 'route:cache') {
        $new = [];
        foreach ($this->bootstrappers as $boot) {
            if ($boot === 'Illuminate\Foundation\Bootstrap\BootProviders') {
                $new[] = 'App\Console\BootstrapDebugbar';
            }
            $new[] = $boot;
        }
        $this->bootstrappers = $new;
    }
    return parent::bootstrap();
}

Then create a file app/Console/BootstrapDebugbar.php with the following content:

<?php
namespace App\Console;

use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Foundation\Application;

class BootstrapDebugbar {
    public function bootstrap(Application $app) {
        // Enable Debugbar in Console mode. This bootstrap class is
        // run just before all services providers are booted.
        $app->config->set('debugbar.enabled', true);
    }
}

5. Ready to use!

All you need to do to use Debugbar is to visit the route you created in step 2. We added it to our menu Blade file:

@can('enableDebugbar', $user)
    <li><a href="{{route('admin::debug::toggle-debugbar')}}">Toggle Debugbar</a></li>
@endcan

@emilv thanks for the steps. It helped a lot.

This method works for activating debugbar for specific IP addresses on production.

I need an advice from people who knows Laravel well, or this my provided way is safe enough. 0.0.0.0 - add your IP you want to activate debugbar

In /config/app.php:
'debug' => env('APP_DEBUG', ($_SERVER['REMOTE_ADDR'] == '0.0.0.0' or $_SERVER['REMOTE_ADDR'] == '0.0.0.0') ? true : false),

In /config/debugbar.php:
'enabled' => null,

In /.env:
Remove line “APP_DEBUG=false”

@GoodJob That works as long as you do not use config caching. If you do want to use config caching, follow my steps instead (skipping steps 1, 2 and 5 if you check IP instead of cookie).

enabled set to null in /config/debugbar.php add too much overhead, my average page response time change from 100ms to 2s, that's not acceptable in my case.

I have to conditionally enable it on with ($_SERVER['REMOTE_ADDR'] == 'my_ip ? true : false)

but this is definitely not a clean solution, since I want to enable debugbar in a middleware which check for admin privileges.

@unitedworx @mikebronner @lvbeck @GoodJob @emilv
To enable debugbar in middleware (when it's off in config and APP_DEBUG=false):
1) add this middleware \Barryvdh\Debugbar\Middleware\InjectDebugbar::class after your middleware (which call \Debugbar::enable())
app\Http\Kernel.php:

'web' => [
           ...
            \App\Http\Middleware\DebugbarEnabler::class, // my middleware
            \Barryvdh\Debugbar\Middleware\InjectDebugbar::class,
        ],

2) create DebugbarEnablerServiceProvider (app\Providers\DebugbarEnablerServiceProvider.php) with this code (which adds web middleware in debugbar css/js and other routes)

public function boot()
    {
        $debugbarRoutes = collect(app('router')->getRoutes()->getRoutesByName())
            ->filter(function ($value, $key) {
                return strpos($key, 'debugbar') !== false;
            });

        foreach ($debugbarRoutes as $route) {
            $action = $route->getAction();
            array_unshift($action['middleware'], 'web');
            $route->setAction($action);
        };
    }

3) make sure that the config\app.php looks like this (Barryvdh\Debugbar\ServiceProvider must be before DebugbarEnablerServiceProvider)

'providers' => [
    ...
    Barryvdh\Debugbar\ServiceProvider::class, // debugbar service provider
    App\Providers\DebugbarEnablerServiceProvider::class, // my service provider
    ...
],

PS. To use debugbar in production, you will need to set APP_DEBUG env variable to false because as written in the documentation:

Once enabled, the collectors are added (and could produce extra overhead), so if you want to use the debugbar in production, disable in the config and only enable when needed.

@ahurov Interesting solution! It does look cleaner than mine.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If this issue is still present on the latest version of this library on supported Laravel versions, please let us know by replying to this issue so we can investigate further.
Thank you for your contribution! Apologies for any delayed response on our side.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

linaspasv picture linaspasv  ·  5Comments

knvpk picture knvpk  ·  5Comments

lozadaOmr picture lozadaOmr  ·  6Comments

innerdev picture innerdev  ·  5Comments

lucasdcrk picture lucasdcrk  ·  3Comments