Defining a Namespace for Laravel 8 Routes

Defining a namespace for Laravel 8 routes

Instead, I would simply uncomment this line in app/Providers/RouteServiceProvider.php which will revert back to the Laravel <8 behavior of automatically prefixing route declarations in 'routes/web.php' 'routes/api.php' with the App\Http\Controllers namespace.

/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* @var string|null
*/
protected $namespace = 'App\\Http\\Controllers';

This commented out property might not be in your app/Providers/RouteServiceProvider.php if you created the project when v8 was first released, (seems it was removed then added back) if not, just add it and uncommnet, and make sure its used in the boot method the prop and it'll work.

public function boot()
{
$this->configureRateLimiting();

$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace($this->namespace) // make sure this is present
->group(base_path('routes/api.php'));

Route::middleware('web')
->namespace($this->namespace) // make sure this is present
->group(base_path('routes/web.php'));
});
}

Route group namespace in Laravel 8

I think laravel drop the feature, because in laravel 8, controller will be Object oriented class

Laravel Routing 7.* Docs.

Laravel Routing 7.* Docs.

Laravel Routing 8.* Docs.

Laravel Routing 8.* Docs.

How to use old Laravel routing style in Laravel 8

You can still use it to some extend (e.g. grouping and prefixing a route) but because you're using a FQCN the namespace is redundant. The major advantage using the "new" routing over of the "old" one is refactoring. When you move or rename your controller with an IDE that supports refactoring like PhpStorm you wouldn't need to manually change the name and group namespace of your controller.

In Laravel 5 you were able to use this route notation too but it wasn't outlined in the documentation.

To achieve a similar feeling, import the namespace and use just your class names and get rid of the namespace-group in the definition.

use App\Http\Controllers\Admin\PanelController;

Route::prefix('admin')->group(function () {
Route::get('panel', [PanelController::class, 'index']);
});

If you just cannot live with the new way of defining routes, uncomment the $namespace property in app/Providers/RouteServiceProvider.php and you're back to the old way.

Error “Target class controller does not exist” when using Laravel 8

You are using Laravel 8. In a fresh install of Laravel 8, there is no namespace prefix being applied to your route groups that your routes are loaded into.

"In previous releases of Laravel, the RouteServiceProvider contained a $namespace property. This property's value would automatically be prefixed onto controller route definitions and calls to the action helper / URL::action method. In Laravel 8.x, this property is null by default. This means that no automatic namespace prefixing will be done by Laravel." Laravel 8.x Docs - Release Notes

You would have to use the Fully Qualified Class Name for your Controllers when referring to them in your routes when not using the namespace prefixing.

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);
// or
Route::get('/users', 'App\Http\Controllers\UserController@index');

If you prefer the old way:

App\Providers\RouteServiceProvider:

public function boot()
{
...

Route::prefix('api')
->middleware('api')
->namespace('App\Http\Controllers') // <---------
->group(base_path('routes/api.php'));

...
}

Do this for any route groups you want a declared namespace for.

The $namespace property:

Though there is a mention of a $namespace property to be set on your RouteServiceProvider in the Release notes and commented in your RouteServiceProvider this does not have any effect on your routes. It is currently only for adding a namespace prefix for generating URLs to actions. So you can set this variable, but it by itself won't add these namespace prefixes, you would still have to make sure you would be using this variable when adding the namespace to the route groups.

This information is now in the Upgrade Guide

Laravel 8.x Docs - Upgrade Guide - Routing

With what the Upgrade Guide is showing the important part is that you are defining a namespace on your routes groups. Setting the $namespace variable by itself only helps in generating URLs to actions.

Again, and I can't stress this enough, the important part is setting the namespace for the route groups, which they just happen to be doing by referencing the member variable $namespace directly in the example.

Update:

If you have installed a fresh copy of Laravel 8 since version 8.0.2 of laravel/laravel you can uncomment the protected $namespace member variable in the RouteServiceProvider to go back to the old way, as the route groups are setup to use this member variable for the namespace for the groups.

// protected $namespace = 'App\\Http\\Controllers';

The only reason uncommenting that would add the namespace prefix to the Controllers assigned to the routes is because the route groups are setup to use this variable as the namespace:

...
->namespace($this->namespace)
...

Laravel 8 Controller does not exist, namespace is in routes and problem only exists on an apache webserver but works locally

Namespaces seem to be case sensitive for the webserver, and I didn't manage to catch the typo. Local artisan and xampp seem to be able to handle it even though it's not correct. The apache webserver had a problem with it. It's supposed to be

use App\Http\Controllers\KnowledgeController;

Route to controller in Laravel 8

TL;DR

Do it like so:

use App\Http\Controllers\PortfolioController;

Route::get('/portfolio', PortfolioController::class)->name('portfolio');
^^^^^^^^^^^^^^^^^^^^^^^^^^


Explanation

Before Laravel 8, routes were namespaced in RouteServiceProvider.php:

protected $namespace = 'App\Http\Controllers';

// ...

protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace) // <----
->group(base_path('routes/web.php'));
}

So, when you defined routes, like in your example:

Route::get('/portfolio', 'PortfolioController')->name('portfolio');
^^^^^^^^^^^^^^^^^^^^^

The PortfolioController string was namespaced with App\Http\Controllers.

However, since Laravel 8 this behaviour has been modified. From the v8 release note:

In Laravel 8.x, this property is null by default. This means that no
automatic namespace prefixing will be done by Laravel. Therefore, in
new Laravel 8.x applications, controller route definitions should be
defined using standard PHP callable syntax:

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

Now, for the particular case you mentioned, __invoke() methods, this is how you should handle them according to the docs:

When registering routes for single action controllers, you do not need
to specify a method:

use App\Http\Controllers\ShowProfile;

Route::get('user/{id}', ShowProfile::class);

Using namespace method in RouteServiceProvder in Laravel package

loadRoutesFrom is a helper that checks to see if the routes are cached or not before registering the routes.

You can start defining a group of routes then call loadRoutesFrom in that group in your provider's boot method:

Route::group([
'domain' => 'api'. config('app.url'), // don't call `env` outside of configs
'namespace' => $this->namespace,
'middleware' => 'api',
], function () {
$this->loadRoutesFrom(__DIR__.'/../../routes/api.php');
});

Or if you prefer the method style of setting the attributes:

Route::domain('api'. config('app.url'))
->namespace($this->namespace)
->middleware('api')
->group(function () {
$this->loadRoutesFrom(__DIR__.'/../../routes/api.php');
});

This is how Laravel Cashier is doing it:

https://github.com/laravel/cashier/blob/10.0/src/CashierServiceProvider.php#L86



Related Topics



Leave a reply



Submit