Laravel 5 can't find class for custom namespace

3.3k views Asked by At

In my Laravel app I'm splitting the front end and back end code into folder. These are app/Http/Controllers/BackEnd and app/Http/Controllers/FrontEnd. Rather than type all that out on every file I thought it would be easier to define two namespaces, BackEnd and FrontEnd. I've edited my composer file to this:

"autoload": {
    "classmap": [
        "app/Models",
        "database"
    ],
    "psr-4": {
        "App\\": "app/",
        "BackEnd\\": "app/Http/Controllers/BackEnd",
        "FrontEnd\\": "app/Http/Controllers/FrontEnd"
    }
},

I then ran composer autodump and set up my route file like this:

Route::group(['prefix' => 'webman', 'middleware' => 'auth', 'namespace' => 'BackEnd'], function()
{
   Route::get('/', ['as' => 'webmanHome', 'uses' => 'HomeController@index']); 
});

But when I browse to localhost:8000/webman/ I just get an error, Class App\Http\Controllers\BackEnd\HomeController does not exist. The controller does exist, this is the file:

<?php namespace BackEnd;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class HomeController extends Controller {

    /**
     * Display the admin home page, showing the front-end menu and "apps" as links to other sections of the ACP.
     *
     * @param Reqeust       $request
     *
     * @return View
     */
    public function index(Request $request)
    {
        return view('backend.index');
    }

}

I've checked vendor/composer/autoload_psr4.php to make sure that the namespace is being defined and it is, this is in the array returned 'BackEnd\\' => array($baseDir . '/app/Http/Controllers/BackEnd'),.

Strangely if I use <?php namespace App\Http\Controllers\BackEnd; at the top of HomeController.php then everything works, why? What am I missing? Why can't autoload find the file with just BackEnd?

3

There are 3 answers

2
Jocke Med Kniven On BEST ANSWER

When setting namespace in Route::group() it is actually appending that to App\Http\Controllers. What you could do is remove it and reference the full path like so:

Route::group(['prefix' => 'webman', 'middleware' => 'auth'], function()
{
    Route::get('/', ['as' => 'webmanHome', 'uses' => '\BackEnd\HomeController@index']); 
});
0
mangonights On

There's an interesting and easy way to get around this... Service Providers.

When the route file is loaded via a provider, the 'App\Http...' is not enforced.

public function boot()
{
    $this->loadRoutesFrom(app_path('Your/Model/routes.php'));
}

Keep in mind no middleware is attached either. Your route group will have to specify a 'web' middleware or you'll go nuts wondering why validation, etc, isn't working anymore....(been there!)

It's a cool way to go about it anyway, using providers leads to more modular code and re-use.

1
Shekar On

Try changing/commenting the below line in RouteServiceProvider.php protected $namespace = 'App\Http\Controllers';