controller
- Define Controller
- Controller & Namespace
- Single behavior controller
- Partial resource routing
- Named resource routing
- Controller middleware
- Resource controller
- Resource controller operation processing
- Specify resource model
- Fake form method
- Route cache
Controller
- Introduction
- Basic Controller
- Control Device middleware
- Resource controller
- Dependency Injection & Controller
- Route Cache
Introduction
In order to replace all request processing logic defined in the form of closures in the routing file, you may want to use control classes to organize these behaviors. Controllers can group related request processing logic into a separate class. Controllers are stored in the
app/Http/Controllers
directory.Basic Controller
Define Controller
The following is an example of a basic controller class. It should be noted that this controller inherits Laravel's built-in base class controller. This base class controller provides some convenient methods, such as the
middleware
method, which can add middleware to the controller behavior:<?php namespace App\Http\Controllers; use App\User; use App\Http\Controllers\Controller; class UserController extends Controller { /** * 显示给定用户的概要文件. * * @param int $id * @return View */ public function show($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } }
You can define a pointer to the controller behavior like this Routing:
Route::get('user/{id}', 'UserController@show');
Now, when a request matches the URI of the specified route, the
show
method in theUserController
controller will be executed. Route parameters will also be passed to this method.{tip} The controller is not required to inherit the base class. However, if the controller does not inherit from the base class, you will not be able to use some convenient functions, such as the
middleware
,validate
anddispatch
methods.Controller & Namespace
It is important to point out that we do not need to specify the complete controller namespace when defining controller routes. Because
RouteServiceProvider
will load the routing file in a routing group containing the namespace, we only need to specify the part of the class name after theApp\Http\Controllers
namespace.If you choose to place the controller in a deeper directory than
App\Http\Controllers
, you need to use a namespace relative toApp\Http\Controllers
as the root namespace The specified class name. Therefore, if your complete controller class name isApp\Http\Controllers\Photos\AdminController
, you should register it in the routing as follows:Route::get('foo', 'Photos\AdminController@method');
Single Behavior Controller
If you want to define a controller that only handles a single behavior, you can place an
__invoke## in the controller # Method:
<?php namespace App\Http\Controllers; use App\User; use App\Http\Controllers\Controller; class ShowProfile extends Controller { /** * 展示给定用户的资料. * * @param int $id * @return View */ public function __invoke($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } }
When registering the route of a single behavior controller, there is no need to specify the method:Route::get('user/{id}', 'ShowProfile');
You can pass themake:controller
command in the Artisan command tool The
--invokableoption to generate a callable controller:
php artisan make:controller ShowProfile --invokable
Controller MiddlewareMiddleware Routes that can be assigned to controllers in route files.Route::get('profile', 'UserController@show')->middleware('auth');
However, it is more convenient to specify the middleware in the controller's constructor. Middleware can be easily assigned to a controller's action using themiddleware
method in the controller's constructor. You can even restrict middleware to 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'); } }
At the same time, the controller also allows you to use a closure to register middleware. This provides a convenient way to define middleware for a single controller without defining the entire middleware class:$this->middleware(function ($request, $next) { // ... return $next($request);});
{tip} You can assign middleware to a controller action A subset; however, it may indicate that your controller is getting very large. It is recommended that you split the controller into multiple smaller controllers.
Resource Controller
Laravel resource routing assigns the typical "CURD (Create, Delete, Modify, Check)" route to a controller with a single line of code. For example, you want to create a controller that handles all HTTP requests for "photos" saved by your app. Using the Artisan command
make:controller
, we can quickly create such a controller:php artisan make:controller PhotoController --resource
This command will generate a controller
app/Http/Controllers/PhotoController.php
. This includes methods for each available resource operation.Next, you can register a resource route to the controller:
Route::resource('photos', 'PhotoController');
This single route declaration creates multiple routes to handle various behaviors on the resource. The generated controller retains methods for each action, including declarative annotations for handling HTTP verbs and URLs.
You can create multiple resource controllers at once by passing array parameters to the
resources
method:Route::resources([ 'photos' => 'PhotoController', 'posts' => 'PostController' ]);
Resource Controller Operation Processing
HTTP Method URI Action Route Name ##GET /photos indexphotos.index GET /photos/create createphotos.create POST /photos storephotos.store GET /photos/{photo} showphotos.show GET /photos/{photo}/edit editphotos.edit PUT/PATCH /photos/{photo} update photos.update DELETE /photos/{photo}
destroy photos.destroy Specify resource model
If you use routing model binding and want to use type hints in resource controller methods, you can use # when generating the controller. ##--model
Options:
php artisan make:controller PhotoController --resource --model=Photo
Fake form methodBecause HTML forms cannot generatePUT
,
PATCH, and
DELETErequests, so you need to add a hidden
_methodfield to fake HTTP actions. This Blade directive
@methodcan create this field for you:
<form action="/foo/bar" method="POST"> @method('PUT') </form>
##Partial resource routingWhen declaring resource routing, you can specify some behaviors that the controller should handle instead of all default behaviors:
Route::resource('photos', 'PhotoController')->only([ 'index', 'show' ]); Route::resource('photos', 'PhotoController')->except([ 'create', 'store', 'update', 'destroy' ]);
API Resource RoutingWhen declaring with When routing resources for APIs, it is usually necessary to exclude routes that display HTML templates, such as
createand
apiResourcesedit
. For convenience, you can use theapiResource
method to automatically exclude these two routes:
You can register it all at once by passing an array to theRoute::apiResource('photos', 'PhotoController');
method Multiple API resource controllers:
create
In order to quickly generate an API resource controller that does not contain theRoute::apiResources([ 'photos' => 'PhotoController', 'posts' => 'PostController' ]);
and
edit
methods, you can executemake: Add the
--apioption to the controller
command:php artisan make:controller API/PhotoController --api
Named resource routingBy default, all resource controller actions have a route name; however, these names can be overridden by passing an array of
nameswith options:
Route::resource('photos', 'PhotoController')->names([ 'create' => 'photos.build' ]);
Named resource routing parametersBy default,
Route::resourcewill create resources based on the "singular" form of the resource name The route parameters for the route. You can easily override each resource by passing
showparameters
parameters in the options array.parameters
The array should be an associative array of resource names and parameter names:
The above list will generate the following URl for theRoute::resource('users', 'AdminUserController')->parameters([ 'users' => 'admin_user' ]);
route of the resource:
/users/{admin_user}
Localized resource URIs
By default,
Route::resource
will use English verbs to create resource URIs. If you need to localize thecreate
andedit
action names, you can useRoute in the
bootmethod of
AppServiceProvider: :resourceVerbs
method implementation.use Illuminate\Support\Facades\Route; /** * 初始化任何应用服务 * * @return void */ public function boot(){ Route::resourceVerbs([ 'create' => 'crear', 'edit' => 'editar', ]); }
Once the action is customized, a resource route registered like
Route::resource('fotos', 'PhotoController')
will generate the following URI:/fotos/crear/fotos/{foto}/editar
Supplementary Resource Controller
If you need to add additional routes to the resource controller beyond the default route, you should call
Route::resource
; Define these routes before; otherwise, the routes defined by theresource
method may inadvertently take precedence over the routes you add:Route::get('photos/popular', 'PhotoController@method'); Route::resource('photos', 'PhotoController');
##Dependency Injection & ControllerConstructor Injection{tip} Remember to keep your controller focused. If you find yourself frequently needing methods outside of typical resource operations, consider splitting your controller into smaller controllers.
<?php namespace App\Http\Controllers; use App\Repositories\UserRepository; class UserController extends Controller{ /** * The user repository instance. */ protected $users; /** * Create a new controller instance. * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } }
Of course, you can enter any Laravel contract. As long as the container can resolve it. Depending on your application, injecting your type hints into the controller will provide better testability. Method InjectionHandling constructor injection, you can also enter type-hinted dependencies in controller methods. The most common use case for method injection is to inject an instance ofIlluminate\Http\Request
into the controller method:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Store a new user. * * @param Request $request * @return Response */ public function store(Request $request) { $name = $request->name; // } }
If your controller also needs to obtain input from the route parameters, add the route Parameters are placed after these dependencies. For example, your route definition looks like this:Route::put('user/{id}', 'UserController@update');
You can still enter theIlluminate\Http\Request
type hint and access it by using the following definition in your controller method
idParameters:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class UserController extends Controller{ /** * Update the given user. * * @param Request $request * @param string $id * @return Response */ public function update(Request $request, $id) { // } }
Route caching
{note} Closure-based routes cannot be cached. Use route caching. You need to convert any closure routes into controller routes.
If your application only uses controller-based routing, then you should take advantage of route caching. Using route caching will greatly reduce the time required to register all application routes. In some cases, route registration is even 100 times faster. To generate a route cache, just execute
route:cache
:php artisan route:cache
After running this command, each request will load the cached route file. Remember, if you add any new routes, you will need to generate a new route cache. Therefore, you should only run the
route:cache
command during project deployment.You can use the
route:clear
command to clear the route cache:php artisan route:clear
This article was first published on the LearnKu.com website.