laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.03k stars 10.85k forks source link

Calling Artisan::call('route:list') produces an error #50782

Closed espenkn closed 4 months ago

espenkn commented 4 months ago

Laravel Version

11.1.0

PHP Version

8.2.17

Database Driver & Version

No response

Description

When i run Artisan::call('route:list')

from a controller I get an error saying Target class [web] does not exist. but if i capture the output with a BufferedOutput the contents of output is the expected value.

Looks like the command is trying resolve the 'web' middleware and that results in a BindingResolutionException.

Is this a bug or a usage error from my side?

Steps To Reproduce


class AdminController extends Controller
{
    function ApiTester()
    {
        Artisan::call('route:list');
        // This view will print the exception
        return view('admin.apitester');
    }
}
joy2362 commented 4 months ago

@esbenp are you trying this in the web route or API route?

espenkn commented 4 months ago

This is in the web route but with sanctum like this (abbreviated)

Route::middleware('auth:sanctum')->group(function() {
    Route::prefix('admin')->controller(AdminController::class)->group(function() {
        Route::get('/apitester', 'ApiTester');
    });
driesvints commented 4 months ago

I'm not sure it makes sense to call this command in that way.

espenkn commented 4 months ago

I'm not sure it makes sense to call this command in that way.

So i have a web page where i can experiment with the API that works and is a great timesaver, but I thought It would be nice to list out the defined API routes in the browser so I dont have to look that up. So for my app this makes perfect sense. I do capture the output and presetnt that in my api tester page and everything works, but this also generates the exception as a side effect. I PRESENTED THE MINIMAL EXAMPLES TO REPORDUCE the issue, not what I do exactly in my app.

joy2362 commented 3 months ago

sorry i'm late but i think instaed of artisan route:list this following function give you everything you need " $routes = Route::getRoutes();"

espenkn commented 3 months ago

Thanks @joy2362 for putting me on the right path. Super happy that you commented since I had more or less given up on this. I managed from your comment to get to this solution witch is enough for me. Thank you so much @joy2362

$routes = Route::getRoutes();
$api_routes = $this->filterApiRoutes($routes->get());
private function filterApiRoutes($routes)
{
    $api_routes = array_filter($routes, function($route) {
        // Check if the uri starts with the api prefix
        return substr($route->uri, 0, 4) == 'api/';
    });

    return $api_routes;
}
<table class="table table-striped">
    <tr>
        <th>Methods</th>
        <th>URI</th>
    </tr>
    @foreach ($routes as $route)
        <tr>
            <td>{{ implode(' | ', $route->methods) }}</td>
            <td>{{ $route->uri }}</td>
        </tr>
    @endforeach
</table>

Still a bit sad that you cant do (without it triggering an exception in the view)

$output = new BufferedOutput();
Artisan::call('route:list', ['--path' => 'api/'], $output);

to get the formated output so i could just <pre> that out though.

joy2362 commented 3 months ago

try this its work for me

\Illuminate\Support\Facades\Artisan::call('route:list' , ['--path' => 'api/']);

$result = \Illuminate\Support\Facades\Artisan::output();

dd($result);
espenkn commented 3 months ago

try this its work for me

\Illuminate\Support\Facades\Artisan::call('route:list' , ['--path' => 'api/']);

$result = \Illuminate\Support\Facades\Artisan::output();

dd($result);

@joy2362 Thanks so much for your assistance, but unfortunately I have the same issue with that approach. The dd is perfect, exactly what I want, but when i pass that into a view it enters into a semi broken exception handling view where I see the error saying Target class [web] does not exist. but the view renders but then wrapped in the typical exception handling view. The data is there and perfect, but the page is wrapped in Laravel's handler. I can post a screen shot later if interesting.

joy2362 commented 3 months ago

would you share your blade file so that i can check what's going wrong?

espenkn commented 3 months ago

@joy2362 First thing tomorrow, thanks :-)

espenkn commented 3 months ago

So sorry for the delay. In blade I don\t have to do anything to trigger the issue, the fact that I have call to Artisan::call('route:list'); in the controller is all that is needed for the page to render like this screen shoot. Notice that my page renders out at the top and the exception pages gets printed bellow, all the data is in the page except that the styling from Laravel interferes a bit with the pages design.

image

joy2362 commented 3 months ago

ok i'll check and let you know it's look interesting issue to me