laravel 學習筆記——路由(路由與控制器、資源路由)
目前我們大致瞭解了laravel下,在開始一個Http程式需要先定義路由。之前的例子中,我們的業務邏輯都是在路由裡實現,這對於簡單的網站或web應用沒什麼問題,當我們需要擴大規模,程式變得複雜,分層的業務邏輯更為適合。這時候,我們就應該使用控制器。
瞭解MVC的都對控制器的作用有所瞭解,控制器是實現主要業務邏輯的。在其他框架,控制器一般就是一個類,laravel也不例外,laravel的控制其結構並沒有什麼特殊。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class HomeController extends Controller {
/**
* 顯示首頁。
*
* @return Response
*/
public function index()
{
return view('home');
}
}
上述例子中就是laravel的控制器結構,沒什麼特別的。可以看得到,Laravel的控制器非常的乾淨,與其他類的耦合度相當的低。得益於laravel的IoC容器,我們很容易實現相當豐富的功能,且不會產生緊密耦合。那麼如何才能訪問到這個控制器裡的邏輯呢?
我們所知道的許多框架,通常有著既定的路由規則,我個人比較熟悉TP,TP的預設路由規則是http://yourdomain/Module/Controller/Action
http://yourdomain/Content/Home/index
,預設會將請求派發至Content模組下的HomeController
類的index
方法。ThinkPHP這種預設路由規則使得框架開箱即用,十分便捷。但是這樣並不靈活,假如我想通過訪問http://yourdomain/user/1
就訪問到UserController
控制器下的show
方法幷包含一個值為1的引數,ThinkPHP你需要修改配置(並且那個配置非常不優雅),亦或者我想要通過向http://yourdomain/topic
POST一個數據以新增一篇文章,處理這個過程的實際是Admin\TopicController
類的create
說到這裡,似乎大家是不是想起了laravel那種路由定義方式的好處了?雖然laravel沒有強加給你既定的路由規則,但你擁有了更多定製的權利,並且laravel定義路由的方式非常優雅,帶給你的體驗非常豐富。另一個好訊息是,定義控制器路由和普通路由有所差別,這個差別是在便利性上的,你將很快感受到這種便利帶給你的好處!
說到現在,已經積累了很多疑惑,我們現在開始正式講述laravel的控制器與控制器路由。
控制器路由
我們之前程式碼示例中,看到了一個十分簡單的控制器,但是要知道,定義了控制器你是無法直接使用的,要知道一個來自客戶端的請求會經過路由,經過解析最終按照規則派發至具體的處理邏輯。
我們知道如何定義一個路由,但之前的路由裡包含了邏輯,我們如何將這個路由的邏輯轉到控制器呢?我們希望通過http://yourdomain/
訪問到我們上面例子中的HomeController
類的index
方法,應該這樣定義一條路由:
Route::get('/', '[email protected]');
例子很簡單。但是這種定義方法會帶來一種問題。
關於laravel的路由定義,很多人看到後有一個疑惑:
每條地址規則都要定義路由,豈不是很累?
這個問題確實是個問題,不過,laravel給了我們一個折中的方案——控制器路由。
控制器路由我認為主要是解決路由定義繁雜的情況,因為大型的應用業務複雜,控制器相當的多,我們不可能每一個控制器的方法都要定義一個路由。Laravel的控制器路由可以完美解決問題:
Route::controller('/', 'HomeController');
我們的控制器方法的寫法也要有所變化:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class HomeController extends Controller {
/**
* 顯示首頁。
*
* @return Response
*/
public function getIndex()
{
return view('home');
}
/**
* 顯示關於介面
*
* @return Response
*/
public function getAbout()
{
return view('about');
}
}
依照上述例子,如果我們訪問地址http://yourdomain/
就會顯示HomeController
的getIndex
方法產生的內容,訪問http://yourdomain/about
,就會顯示getAbout
方法產生的內容。除了使用如get{Method}
這種格式,還可以有post{Method}
、delete{Method}
等,至於字首get
,post
等代表的意義,應該猜得出吧?
相關部分,官方文件已經很詳細寫出。可以繼續去了解,上述內容屬於控制器章節的隱式控制器
。
現在我們已經看到,這樣的定義我們可以不用再給控制器的每一個方法定義一個路由,只需給控制器定義一個路由即可。
資源控制器
RESTful是一種設計思想、一種普遍接受的規範。我們的資源控制器,和RESTful有著莫大的聯絡,要理解資源控制器,必須先了解RESTful。
REST這個詞,是Roy Thomas Fielding在他2000年的博士論文中提出的。
Fielding是一個非常重要的人,他是HTTP協議(1.0版和1.1版)的主要設計者、Apache伺服器軟體的作者之一、Apache基金會的第一任主席。所以,他的這篇論文一經發表,就引起了關注,並且立即對網際網路開發產生了深遠的影響。
Fielding將他對網際網路軟體的架構原則,定名為REST,即Representational State Transfer的縮寫。我對這個片語的翻譯是"表現層狀態轉化"。
如果一個架構符合REST原則,就稱它為RESTful架構。
要理解RESTful架構,最好的方法就是去理解Representational State Transfer這個片語到底是什麼意思,它的每一個詞代表了什麼涵義。如果你把這個名稱搞懂了,也就不難體會REST是一種什麼樣的設計。
大家一定要閱讀該文章,理解RESTful架構,文章十分清晰的講述了RESTful,本文就不再重複熬述。
Laravel的資源控制器原生的支援了RESTful架構。其實laravel的資源控制器和其他控制器沒什麼直接區別,只是對控制器類的方法和結構略有規定,不過我們並不要手動建立資源控制器,我們可以利用laravel的命令列工具——artisan
。
在laravel框架根目錄下,通過命令列輸入命令
php artisan make:controller ArticleController
就可以建立一個名為ArticleController
的資源控制器,檔案預設在app/Http/Controllers
下。我們開啟ArticleController.php
,發現裡面已經寫好了許多方法,比如index、create、show等等。分別是什麼意思?如何在路由定義才能訪問到?
我們如果要在路由裡定義一個資源控制器只需要一條:
Route::resource('article', 'ArticleController');
這個時候,肯定有人會疑惑,那訪問的地址規則呢?如果你已經瞭解了RESTful,再去閱讀以下官方文件,基本就已經明白了。我就著上述的控制器、路由,來說明。先看一張表:
請求方法 | 請求URI | 對應的控制器方法 | 代表的意義 |
---|---|---|---|
GET | /article | index | 索引/列表 |
GET | /article/create | create | 建立(顯示錶單) |
POST | /article | store | 儲存你建立的資料 |
GET | /article/{id} | show | 顯示對應id的內容 |
GET | /article/{id}/edit | edit | 編輯(顯示錶單) |
PUT/PATCH | /article/{id} | save | 儲存你編輯的資料 |
GET | /article/{id} | destroy | 刪除 |
大概挑兩條解釋。
我定義了個資源路由Route::resource('article', 'ArticleController');
。
當我訪問地址http://yourdomain/article
,相當於訪問控制器ArticleController
的index
方法。
當我訪問地址http://yourdomain/article/create
,就會訪問到create
方法。
當我通過POST提交資料至地址http://yourdomain/article
,相當於由store
方法處理。
現在理解了嗎?通過資源控制器,我們很容易實現一個符合RESTful架構的介面,這種很適合作為APP後端開發時使用。這種規範下,不但訪問策略清晰易理解,更容易維護。也使你的架構更為合理和現代化。
當然,複雜的業務邏輯使得資源控制器還不僅僅這麼使用,但當你理解了這種最為基本的,其他的也不會太難。文件中對控制器的其他部分做出相當詳細的描寫,本著作為文件的補充,這些文件中已經存在且足夠理解的,就不再複述。