[ Laravel 5.5 文档 ] 处理用户请求 —— Laravel 应用的入口:路由系列之基础入门篇

基本路由

最基本的 Laravel 路由只接收一个 URI 和一个闭包,并以此为基础提供一个非常简单优雅的路由定义方法:

Route::get('hello', function () {
    return 'Hello, Welcome to LaravelAcademy.org';
});

我们以在安装配置文档中新建的 blog 应用为例,在 routes/web.php 中定义该路由:

在浏览器中通过 http://blog.dev/hello (我使用 Valet 作为开发环境,故而对应域名是 blog.dev,实际域名以自己配置的为准)即可访问我们刚刚定义的路由,页面输出内容如下:

Hello, welcome to LaravelAcademy.org

默认路由文件

所有 Laravel 路由都定义在位于 routes 目录下的路由文件中,这些文件通过框架自动加载,相应逻辑位于 app/Providers/RouteServiceProvider 类(后面我们在讲 Laravel 启动过程的时候会详细讨论这部分逻辑)。routes/web.php 文件定义了 Web 界面的路由,这些路由被分配到了 web 中间件组,从而可以使用 session 和 csrf 保护等功能。routes/api.php 中的路由是无状态的,这是因为被分配到了 api 中间件组。

对大多数应用而言,都是从 routes/web.php 文件开始定义路由。定义在 routes/web.php 中的路由可以通过在浏览器地址栏输入相应的 URL 进行访问,例如,你可以通过 http://blog.dev/user 访问下面的路由:

Route::get('/user', 'UsersController@index');

正如前面所提到的,定义在 routes/api.php 文件中的路由通过 app/Providers/RouteServiceProvider 的处理被嵌套在一个路由中间件组中,在这个路由中间件组中,所有路由会被自动添加 /api 前缀,所以你不需要再到路由文件中为每个路由手动添加,你可以通过编辑 RouteServiceProvider 类来修改路由前缀以及其他的路由中间件组选项:

支持的请求方式

我们可以注册路由来响应任何 HTTP 请求动作:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

有时候还需要注册一个路由响应多种 HTTP 请求动作 —— 这可以通过 match 方法来实现。或者,可以使用 any 方法注册一个路由来响应所有 HTTP 请求动作:

Route::match(['get', 'post'], 'foo', function () {
    return 'This is a request from get or post';
});

Route::any('bar', function () {
    return 'This is a request from any HTTP verb';
});

测试 GET 请求的时候直接在浏览器中输入请求地址即可,测试 POST 请求可以通过客户端工具,比如 Advanced REST Client,该工具可以在 Chrome 应用商店下载到,此外如果上面的路由是定义在 routes/web.php 的话,在测试 POST 请求之前,需要将对应路由取消 CSRF 保护检查,否则会返回 419 状态码导致无法请求成功,取消的方法是在 app/Http/Middleware/VerifyCsrfToken 中设置排除检查路由:

下面我们来测试下 POST 请求:

如果路由是定义在 routes/api.php 的话,则无需关注 CSRF 保护问题,比如我们在 routes/api.php 定义 bar 路由,并且在 VerifyCsrfToken$except 属性数组中移除 bar,然后我们测试下对 http://blog.dev/api/bar 的 POST 请求:

正如我们所预测的,完全没有任何问题,背后的原因是因为 web 路由文件中定义的路由都位于 web 中间件组,该中间件组默认启用 CSRF 保护检查,而 api 路由文件位于 api 中间件组,该中间件组下的路由主要用于 第三方 API 请求,没办法进行 CSRF 检查,所以不需要做任何处理。

CSRF 保护

routes/web.php 路由文件中所有请求方式为 PUTPOSTDELETE 的路由对应的 HTML 表单都必须包含一个 CSRF 令牌字段,否则,请求会被拒绝。关于 CSRF 的更多细节,可以参考 CSRF文档

<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>

还是以上面的 foo 路由为例,如果我们不在 VerifyCsrfToken 中间件中排除对它的检查(事实上,这样的操作也不安全),那么就需要在表单提交中带上 csrf_token 字段:

这样,当我们访问 http://blog.dev/form 然后在页面点击提交按钮后,页面会跳转到 http://blog.dev/foo 并显示如下内容:

This is a request from get or post

表单方法伪造

HTML 表单不支持 PUTPATCH 或者 DELETE 请求方法,因此,在 HTML 表单中调用 PUTPATCHDELETE 路由时,需要添加一个隐藏的 _method 字段,其值被用作该表单的 HTTP 请求方法:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

还可以直接使用辅助函数 method_field 来实现这一功能:

{{ method_field('PUT') }}

路由重定向

如果你需要定义一个重定向到其他 URI 的路由,可以使用 Route::redirect 方法,该方法非常方便,以至于你不需要再定义额外的路由或控制器来执行简单的重定向逻辑:

Route::redirect('/here', '/there', 301);

其中 here 表示原路由,there 表示重定向之后的路由,301 是一个 HTTP 状态码,用于标识重定向。

路由视图

如果你的路由需要返回一个视图,可以使用 Route::view 方法,和 redirect 方法类似,这个方法也很方便,以至于你不需要在额外定义一个路由或控制器。view 方法接收一个 URI 作为第一个参数,以及一个视图名称作为第二个参数,此外,你还可以提供一个数组数据传递到该视图方法作为可选的第三个参数,该数组数据可用于视图中的数据渲染:

Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => '学院君']);

我们在 routes/web.php 定义一个路由视图如下:

为了保证可以共用 welcome.blade.php 这个视图文件,我们也对默认提供的 / 路由做了调整,接下来,我们需要修改 resources/views/welcome.blade.php 代码以支持 website数据变量:

我们将原来写死的 Laravel 文本调整为支持变量传入的方式,这样,我们就可以在浏览器中通过 http://blog.dev/view 访问路由视图了:

学院君 has written 715 articles

资深PHP工程师,Laravel学院院长

9 thoughts on “[ Laravel 5.5 文档 ] 处理用户请求 —— Laravel 应用的入口:路由系列之基础入门篇

    1. php_zk says:

      加上index.php就行了,
      laravel/laravel55/public/index.phphello
      自己发的问起为什么连删除的权限都没有,最尴尬的是没人回答,学院君能否把我发的问题和这个一起删了

    2. lucifer says:

      在你的虚拟主机配置中(貌似你没有开启虚拟主机)添加
      AllowOverride All
      例如:

      DocumentRoot “${SRVROOT}/htdocs/composer_laravel/public”
      ServerName mylaravel.com

      AllowOverride All

      否则,.htaccess文件不会生效。添加后,则会进行url美化操作(即去掉了index.php)

      1. kobecode says:

        我的路由是这样的:Route::redirect(‘/foo’, ‘/hello’, 301);
        然后报错:Not Found The requested URL /foo was not found on this server.
        我的‘/foo’、’/hello‘都是存在的:Route::get(‘/foo’, function () {
        return ‘this is a request from get or post’;
        });
        Route::get(‘hello’, function () {
        return ‘hello, welcome to LaravelAcademy.org’;
        });

发表评论

标记为*的字段是必填项(邮箱地址不会被公开)

你可以使用这些HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>