基礎(chǔ) ―― HTTP 控制器

2018-02-24 15:38 更新

基礎(chǔ) —— HTTP 控制器

1、簡介

將所有的請求處理邏輯都放在單個routes.php中肯定是不合理的,你也許還希望使用控制器請求封裝到一個類中進(jìn)行處理。通??刂破鞔娣旁?code>app/Http/Controllers目錄中。

2、基本控制器

下面是一個基本控制器類的例子。所有的Laravel控制器應(yīng)該繼承自Laravel自帶的控制器基類Controller

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 為指定用戶顯示詳情
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        return view('user.profile', ['user' => User::findOrFail($id)]);
    }
}

我們可以像這樣定義指向該控制器動作的路由:

Route::get('user/{id}', 'UserController@showProfile');

現(xiàn)在,如果一個請求匹配上面的路由URI,UserControllershowProfile方法就會被執(zhí)行。當(dāng)然,路由參數(shù)也會被傳遞給這個方法。

2.1 控制器&命名空間

你應(yīng)該注意到我們在定義控制器路由的時候沒有指定完整的控制器命名空間,而只是定義了App\Http\Controllers之后的部分。默認(rèn)情況下,RouteServiceProvider將會在一個路由分組中載入routes.php文件,并且該路由分組指定定了分組中路由控制器所在的命名空間。

如果你在App\Http\Controllers目錄下選擇使用PHP命名空間嵌套或組織控制器,只需要使用相對于App\Http\Controllers命名空間的指定類名即可。因此,如果你的完整控制器類是App\Http\Controllers\Photos\AdminController,你可以像這樣注冊路由:

Route::get('foo', 'Photos\AdminController@method');

2.2 命名控制器路由

和閉包路由一樣,可以指定控制器路由的名字:

Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);

設(shè)置好控制器路由后,就可以使用幫助函數(shù)action很方便地為控制器動作生成對應(yīng)的URL:

$url = action('FooController@method');

你還可以使用幫助函數(shù)route來為已命名的控制器路由生成對應(yīng)的URL:

$url = route('name');

3、控制器中間件

中間件可以像這樣分配給控制器路由:

Route::get('profile', [
    'middleware' => 'auth',
    'uses' => 'UserController@showProfile'
]);

但是,將中間件放在控制器構(gòu)造函數(shù)中更方便,在控制器的構(gòu)造函數(shù)中使用middleware方法你可以很輕松的分配中間件給該控制器。你甚至可以限定該中間件應(yīng)用到該控制器類的指定方法:

class UserController extends Controller
{
    /**
     * 實(shí)例化一個新的 UserController 實(shí)例
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');

        $this->middleware('log', ['only' => ['fooAction', 'barAction']]);

        $this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]);
    }
}

4、RESTful資源控制器

Laravel的資源控制器使得構(gòu)建圍繞資源的RESTful控制器變得毫無痛苦,例如,你可能想要在應(yīng)用中創(chuàng)建一個控制器,用于處理關(guān)于圖片存儲的HTTP請求,使用Artisan命令make:controller,我們可以快速創(chuàng)建這樣的控制器:

php artisan make:controller PhotoController

該Artisan命令將會生成一個控制器文件app/Http/Controllers/PhotoController.php,這個控制器包含了每一個資源操作對應(yīng)的方法。

接下來,可以為該控制器注冊一個資源路由:

Route::resource('photo', 'PhotoController');

這個路由聲明包含了處理圖片資源RESTful動作的多個路由,相應(yīng)地,Artisan生成的控制器也已經(jīng)為這些動作設(shè)置了對應(yīng)的處理方法。

4.1 資源控制器處理的動作

方法 路徑 動作 路由名稱
GET /photo index photo.index
GET /photo/create create photo.create
POST /photo store photo.store
GET /photo/{photo} show photo.show
GET /photo/{photo}/edit edit photo.edit
PUT/PATCH /photo/{photo} update photo.update
DELETE /photo/{photo} destroy photo.destroy

4.2 只定義部分資源路由

聲明資源路由時可以指定該路由處理的動作子集:

Route::resource('photo', 'PhotoController',
                ['only' => ['index', 'show']]);

Route::resource('photo', 'PhotoController',
                ['except' => ['create', 'store', 'update', 'destroy']]);

4.3 命名資源路由

默認(rèn)情況下,所有資源控制器動作都有一個路由名稱,然而,我們可以通過傳入names數(shù)組來覆蓋這些默認(rèn)的名字:

Route::resource('photo', 'PhotoController',
                ['names' => ['create' => 'photo.build']]);

4.4 嵌套資源

有時候我們需要定義路由到“嵌套”資源。例如,一個圖片資源可能擁有多條“評論”,要“嵌套”資源控制器,在路由聲明中使用“.”號即可:

Route::resource('photos.comments', 'PhotoCommentController');

該路由將注冊一個嵌套的資源,使用URL訪問方式如下:
photos/{photos}/comments/{comments}.

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class PhotoCommentController extends Controller
{
    /**
     * 顯示指定照片評論
     *
     * @param  int  $photoId
     * @param  int  $commentId
     * @return Response
     * @translator http://laravelacademy.org
     */
    public function show($photoId, $commentId)
    {
        //
    }
}

4.5 補(bǔ)充資源控制器

如果有必要在默認(rèn)資源路由之外添加額外的路由到資源控制器,應(yīng)該在調(diào)用Route::resource之前定義這些路由;否則,通過resource方法定義的路由可能無意中優(yōu)先于補(bǔ)充的額外路由:

Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');

擴(kuò)展閱讀:實(shí)例教程——創(chuàng)建RESTFul風(fēng)格控制器實(shí)現(xiàn)文章增刪改查

5、隱式控制器

Laravel允許你只定義一個路由即可訪問控制器類中的所有動作,首先,使用Route::controller方法定義一個路由,該controller方法接收兩個參數(shù),第一個參數(shù)是控制器處理的baseURI,第二個參數(shù)是控制器的類名:

Route::controller('users', 'UserController');

接下來,添加方法到控制器,方法名應(yīng)該以HTTP請求方法開頭:

<?php

namespace App\Http\Controllers;

class UserController extends Controller
{
    /**
     * 響應(yīng) GET /users 請求
     */
    public function getIndex()
    {
        //
    }

    /**
     * 響應(yīng) GET /users/show/1 請求
     */
    public function getShow($id)
    {
        //
    }

    /**
     * 響應(yīng) GET /users/admin-profile 請求
     */
    public function getAdminProfile()
    {
        //
    }

    /**
     * 響應(yīng) POST /users/profile 請求
     */
    public function postProfile()
    {
        //
    }
}

在上例中可以看到,getIndex方法將會在訪問控制器處理的默認(rèn)URI——users時被調(diào)用。

5.1?分配路由名稱

如果你想要命名該控制器中的一些路由,可以將一個名稱數(shù)組作為第三個參數(shù)傳遞到該controller方法:

Route::controller('users', 'UserController', [
    'getShow' => 'user.show',
]);

6、依賴注入?& 控制器

6.1 構(gòu)造函數(shù)注入

Laravel使用服務(wù)容器解析所有的Laravel控制器,因此,可以在控制器的構(gòu)造函數(shù)中類型聲明任何依賴,這些依賴會被自動解析并注入到控制器實(shí)例中:

<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use App\Repositories\UserRepository;

class UserController extends Controller
{
    /**
     * The user repository instance.
     */
    protected $users;

    /**
     * 創(chuàng)建新的控制器實(shí)例
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
}

當(dāng)然,你還可以類型提示任何Laravel契約,如果容器可以解析,就可以進(jìn)行類型提示。

6.2 方法注入

除了構(gòu)造函數(shù)注入之外,還可以在控制器的動作方法中進(jìn)行依賴的類型提示,例如,我們可以在某個方法中類型提示Illuminate\Http\Request實(shí)例:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 存儲新用戶
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

如果控制器方法期望輸入路由參數(shù),只需要將路由參數(shù)放到其他依賴之后,例如,如果你的路由定義如下:

Route::put('user/{id}', 'UserController@update');

你需要通過定義控制器方法如下所示來類型提示Illuminate\Http\Request并訪問路由參數(shù)id

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    /**
     * 更新指定用戶
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     * @translator http://laravelacademy.org
     */
    public function update(Request $request, $id)
    {
        //
    }
}

7、路由緩存

如果你的應(yīng)用完全基于路由使用控制器,可以使用Laravel的路由緩存,使用路由緩存將會極大減少注冊所有應(yīng)用路由所花費(fèi)的時間開銷,在某些案例中,路由注冊速度甚至能提高100倍!想要生成路由緩存,只需執(zhí)行Artisan命令route:cache:

php artisan route:cache

就這么簡單!你的緩存路由文件現(xiàn)在取代app/Http/routes.php文件被使用,記住,如果你添加新的路由需要重新生成路由緩存。因此,只有在項(xiàng)目開發(fā)階段你才會運(yùn)行route:cache命令。

想要移除緩存路由文件,使用route:clear命令即可:

php artisan route:clear
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號