目前我们大致了解了 laravel 下,在开始一个 Http 程序需要先定义路由。之前的例子中,我们的业务逻辑都是在路由里实现,这对于简单的网站或 web 应用没什么问题,当我们需要扩大规模,程序变得复杂,分层的业务逻辑更为适合。这时候,我们就应该使用控制器。

了解 MVC 的都对控制器的作用有所了解,控制器是实现主要业务逻辑的。在其他框架,控制器一般就是一个类,laravel 也不例外,laravel 的控制其结构并没有什么特殊。

  1. <?php
  2. namespaceApp\Http\Controllers;
  3. useApp\Http\Controllers\Controller;
  4. classHomeControllerextendsController{
  5. /**
  6. * 显示首页。
  7. *
  8. * @return Response
  9. */
  10. publicfunction index()
  11. {
  12. return view('home');
  13. }
  14. }

上述例子中就是 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​​ 方法,且该方法只接受 POST 请求,这时候似乎大多数框架就要通过写更多的代码实现了。


说到这里,似乎大家是不是想起了 laravel 那种路由定义方式的好处了?虽然 laravel 没有强加给你既定的路由规则,但你拥有了更多定制的权利,并且 laravel 定义路由的方式非常优雅,带给你的体验非常丰富。另一个好消息是,定义控制器路由和普通路由有所差别,这个差别是在便利性上的,你将很快感受到这种便利带给你的好处!


说到现在,已经积累了很多疑惑,我们现在开始正式讲述 laravel 的控制器与控制器路由。


控制器路由

我们之前代码示例中,看到了一个十分简单的控制器,但是要知道,定义了控制器你是无法直接使用的,要知道一个来自客户端的请求会经过路由,经过解析最终按照规则派发至具体的处理逻辑。

我们知道如何定义一个路由,但之前的路由里包含了逻辑,我们如何将这个路由的逻辑转到控制器呢?我们希望通过 ​​http://yourdomain/​​​ 访问到我们上面例子中的 ​​HomeController​​​类的 ​​index​​ 方法,应该这样定义一条路由:

  1. Route::get('/','HomeController@index');

例子很简单。但是这种定义方法会带来一种问题。


关于laravel的路由定义,很多人看到后有一个疑惑:

每条地址规则都要定义路由,岂不是很累?

这个问题确实是个问题,不过,laravel 给了我们一个折中的方案——控制器路由。


控制器路由我认为主要是解决路由定义繁杂的情况,因为大型的应用业务复杂,控制器相当的多,我们不可能每一个控制器的方法都要定义一个路由。Laravel 的控制器路由可以完美解决问题:

  1. Route::controller('/','HomeController');

我们的控制器方法的写法也要有所变化:

  1. <?php
  2. namespaceApp\Http\Controllers;
  3. useApp\Http\Controllers\Controller;
  4. classHomeControllerextendsController{
  5. /**
  6. * 显示首页。
  7. *
  8. * @return Response
  9. */
  10. publicfunction getIndex()
  11. {
  12. return view('home');
  13. }
  14. /**
  15. * 显示关于界面
  16. *
  17. * @return Response
  18. */
  19. publicfunction getAbout()
  20. {
  21. return view('about');
  22. }
  23. }

依照上述例子,如果我们访问地址 ​​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框架根目录下,通过命令行输入命令

  1. php artisan make:controller ArticleController

就可以创建一个名为 ​​ArticleController​​​ 的资源控制器,文件默认在 ​​app/Http/Controllers​​​下。我们打开 ​​ArticleController.php​​,发现里面已经写好了许多方法,比如 index、create、show 等等。分别是什么意思?如何在路由定义才能访问到?

我们如果要在路由里定义一个资源控制器只需要一条:

  1. 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

保存你编辑的数据

DELETE

/article/{id}

destroy

删除

大概挑两条解释。

我定义了个资源路由 ​​Route::resource('article', 'ArticleController');​​​。当我访问地址 ​​http://yourdomain/article​​​ ,相当于访问控制器 ​​ArticleController​​​ 的 ​​index​​​方法。当我访问地址 ​​http://yourdomain/article/create​​​ ,就会访问到 ​​create​​​ 方法。当我通过 POST 提交数据至地址 ​​http://yourdomain/article​​​,相当于由 ​​store​​ 方法处理。

现在理解了吗?通过资源控制器,我们很容易实现一个符合 RESTful 架构的接口,这种很适合作为 APP 后端开发时使用。这种规范下,不但访问策略清晰易理解,更容易维护。也使你的架构更为合理和现代化。

当然,复杂的业务逻辑使得资源控制器还不仅仅这么使用,但当你理解了这种最为基本的,其他的也不会太难。文档中对控制器的其他部分做出相当详细的描写,本着作为文档的补充,这些文档中已经存在且足够理解的,就不再复述。