barryvdh / laravel-debugbar

Debugbar for Laravel (Integrates PHP Debug Bar)
MIT License
17.4k stars 1.56k forks source link

Fix editor link to Livewire components (e.g. when they are used for routes) #1582

Closed Evertt closed 7 months ago

Evertt commented 7 months ago

I really love the editor link feature. It's just so convenient. But it fails in my current project where I used Livewire components for nearly everything. Especially when I use a Livewire component as a route. It either isn't able to resolve any file related to the component at all. Like you can see here:

image

I hope you notice that there's no row at the bottom of that table called file with a clickable path link.

At some routes it does figure out some file path that I can open in my editor, but it's the wrong file path. See here:

image

I'm guessing this has to do with the fact that the invoked method for the route is __invoke which does indeed exist on the parent class Component that all Livewire components extend from. But can't you just make an exception in your path-resolving code that if you can figure out that the controller of a route is a Livewire component, that you will resolve the file path to refer to the specific component that was actually registered as the route's controller, instead of Livewire's parent Component class?

Edit

Okay, wow, I did not expect this to work, but I was able to fix it in user-land. Though of course if would be nice if this could be natively supported by either Debugbar or Livewire. But anyway, here's how I fixed it:

<?php

namespace App\Http\Middleware;

use Illuminate\Support\Str;

class LivewireRouteResolver
{
    public function handle($request, $next)
    {
        $route = $request->route();
        $action = $route->getAction();
        $response = $next($request);

        $isUsing = $action['controller'] ?? $action['uses'];

        if (!is_string($isUsing)) return $response;
        if (!Str::startsWith($isUsing, 'App\Http\Livewire')) return $response;

        $componentNamespace = str_replace('@__invoke', '', $isUsing);

        $route->setAction(array_merge($action, [
            'controller' => "$componentNamespace@render",
            'uses' => "$componentNamespace@render",
        ]));

        return $response;
    }
}

And then of course I registered that middleware at the end of the list of 'web' middleware.

erikn69 commented 7 months ago

Hi try #1583