Controllers
Introduction
Instead of defining all of your request handling logic as Closures in route files, you may wish to organize this behavior using Controller classes. Controllers can group related request handling logic into a single class. Controllers are stored in the app/Http/Controllers
directory.
Basic Controllers
Defining Controllers
Below is an example of a basic controller class. Note that the controller extends the base controller class included with Laravel. The base class provides a few convenience methods such as the middleware
method, which may be used to attach middleware to controller actions:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return View
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
You can define a route to this controller action like so:
Route::get('user/{id}', 'UserController@show');
Now, when a request matches the specified route URI, the show
method on the UserController
class will be executed. The route parameters will also be passed to the method.
Controllers are not required to extend a base class. However, you will not have access to convenience features such as the middleware
, validate
, and dispatch
methods.
Controllers & Namespaces
It is very important to note that we did not need to specify the full controller namespace when defining the controller route. Since the RouteServiceProvider
loads your route files within a route group that contains the namespace, we only specified the portion of the class name that comes after the App\Http\Controllers
portion of the namespace.
If you choose to nest your controllers deeper into the App\Http\Controllers
directory, use the specific class name relative to the App\Http\Controllers
root namespace. So, if your full controller class is App\Http\Controllers\Photos\AdminController
, you should register routes to the controller like so:
Route::get('foo', 'Photos\AdminController@method');
Single Action Controllers
If you would like to define a controller that only handles a single action, you may place a single __invoke
method on the controller:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return View
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
When registering routes for single action controllers, you do not need to specify a method:
Route::get('user/{id}', 'ShowProfile');
You may generate an invokable controller by using the --invokable
option of the make:controller
Artisan command:
php artisan make:controller ShowProfile --invokable
Controller Middleware
Middleware may be assigned to the controller's routes in your route files:
Route::get('profile', 'UserController@show')->middleware('auth');
However, it is more convenient to specify middleware within your controller's constructor. Using the middleware
method from your controller's constructor, you may easily assign middleware to the controller's action. You may even restrict the middleware to only certain methods on the controller class:
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
Controllers also allow you to register middleware using a Closure. This provides a convenient way to define a middleware for a single controller without defining an entire middleware class:
$this->middleware(function ($request, $next) {
// ...
return $next($request);
});
You may assign middleware to a subset of controller actions; however, it may indicate your controller is growing too large. Instead, consider breaking your controller into multiple, smaller controllers.