介绍
观看本篇前,建议先了解何谓 MVC 模式,简单说控制器的作用就像是交通警察,应用程式在接收 HTTP 请求后,负责将正确的资料从资料库或其他储存机制取出并回传给使用者,回传的内容可以是一个 view 档案或一则简单的讯息端看开发者如何定义,还有就是不建议将应用程式的所有逻辑处理都写进控制器 ,比较好的作法是让控制器只负责解析来自 HTTP 请求的意图,并引导应用程式的其余部分去处理这些逻辑。
新增控制器
Laravel 的控制器档案都放在 app/Http/Controllers 目录中,并且 artisan 也提供方便的语法来新增:
$ php artisan make:controller DemoController
上述语法会产生一名称为 DemoController.php 的档案如下,笔者在这边自行定义了一个简单的方法 index:
<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;class DemoController extends Controller{ public function index() { return 'Hello, World !!'; }}
接着如同上一篇的做法,我们将此控制器挂上一个路由:
<?phpuse Illuminate\Support\Facades\Route;Route::get('/index', 'App\Http\Controllers\DemoController@index');
最后造访「/index」即可看到 Hello, World !! 讯息。
单一动作控制器
若你撰写的控制器只打算匹配一个路由,你可以不用为了替方法想名称而烦恼,只需将你的方法命名为 __invoke:
<?php namespace App\Http\Controllers;use Illuminate\Http\Request; class DemoController extends Controller{ public function __invoke() { return 'Hello, World !!'; }}
这时路由定义可以不标注方法的名称,Laravel 会将整个类别当做函式呼叫:
<?phpuse Illuminate\Support\Facades\Route;Route::get('/index', 'App\Http\Controllers\DemoController');
控制器中介层
除了在路由中使用中介层外,控制器也可以在建构式中使用中介层以及套用在指定的方法上:
<?php namespace App\Http\Controllers;use Illuminate\Http\Request; class DemoController extends Controller{ public function __construct() { $this->middleware('auth'); $this->middleware('log')->only('index'); $this->middleware('subscribed')->except('store'); }}
资源控制器
当你为了一项「资源」的 CRUD 处理而撰写控制器时,Laravel 提供一个很好的方法让你一次绑定整个资源,这边以资源「照片」做为示範:
$ php artisan make:controller PhotoController --resource
这时我们会发现档案内已经预先定义好几个方法:
<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;class PhotoController extends Controller{ public function index() { // } public function create() { // } public function store(Request $request) { // } public function show($id) { // } public function edit($id) { // } public function update(Request $request, $id) { // } public function destroy($id) { // }}
接着我们定义一个路由来指向 PhotoController 这个控制器:
<?phpuse Illuminate\Support\Facades\Route;Route::resource('/photos', 'App\Http\Controllers\PhotoController');
最后我们输入以下 artisan 指令列出可用路由的清单:
$ php artisan route:list
可以发现有 7 组 Laravel 帮我们设定好的路由完整匹配 PhotoController 控制器内的 7 个方法,这样便可以省下命名与重複定义路由的功夫。
有需要的话,还可以指定要执行的路由,而不是默认值的全部:
<?phpuse Illuminate\Support\Facades\Route;/* 只会执行匹配控制器中 index、show 两个方法的路由 */Route::resource('photos', 'App\Http\Controllers\PhotoController')->only([ 'index', 'show']);/* index、show 两个方法的路由不执行,其他的都会执行 */Route::resource('photos', 'App\Http\Controllers\PhotoController')->except([ 'index', 'show']);
API 资源控制器
在为你的 API 定义资源控制器所匹配的路由时,可以使用 apiResource() 来排除 create、edit 这两组路由:
<?phpuse Illuminate\Support\Facades\Route;Route::apiResource('photos', 'App\Http\Controllers\PhotoController');
可以透过将阵列传递给 apiResource() 达到一次定义多组资源控制器:
<?phpuse Illuminate\Support\Facades\Route;Route::apiResources([ 'photos' => 'App\Http\Controllers\PhotoController', 'resources' => 'App\Http\Controllers\ResourceController',]);
而要快速新增排除 create、edit 方法的 API 资源控制器时,artisan 也有提供方便的指令:
php artisan make:controller PhotoController --api