🦄 2024 独立开发者训练营,一起创业!(早鸟优惠在1天后结束)查看介绍 / 立即报名 →

Laravel 5 中文手册(三):路由 Routing

基本路由

应用里的大部分的路由都是在 app/Http/routes.php 这个文件里定义的,这个文件会被 App\Providers\RouteServiceProvider 这个类载入进来。最基本的路由就是一个简单的 URI 带一个 Closure:

基本的 GET 路由

Route::get('/', function()
{
    return 'Hello World';
});

当访问应用的根(/)的时候,就会使用上面定义的这个路由,这个路由做的事,就是使用在这个路由里的 Closure,也就是匿名函数,这里就是返回 Hello World 这几个字。

其它的基本路由

Route::post('foo/bar', function()
{
    return 'Hello World';
});

Route::put('foo/bar', function()
{
    //
});

Route::delete('foo/bar', function()
{
    //
});

Route 的 post 方法定义的是接收 POST 类型的请求的路由,比如当用户把表单提交到 foo/bar 这个地址的时候,就会用上面使用 post 方法定义的那个路由。Route 的 put 方法定义的路由接收 PUT 请求,Route 的 delete 方法定义的路由接收 DELETE 请求。

定义一个有多个动作的路由

Route::match(['get', 'post'], '/', function()
{
    return 'Hello World';
});

上面用 Route 的 match 方法定义的路由,会同时接收 GET 与 POST 类型的请求。

定义可以响应任何 HTTP 动作的路由

Route::any('foo', function()
{
    return 'Hello World';
});

一般你需要为路由生成 URL,可以使用 url 这个帮手去做:

$url = url('foo');

CSRF 保护

Laravel 可以很容易保护应用免受 CSRF(Cross-site request forgeries) 的危险,CSRF 就是跨站请求身份欺诈,也就是已经在你的网站上注册并且登录的用户,在访问一些危险网站的时候,这些网站可能会利用这个用户的身份,对你的网站去执行一些动作。

Laravel 会为每个用户的会话自动生成一个 CSRF “token”,这个 token 可以确定对网站的请求是来自真正的登录的用户,而不是那些危险的网站。

在表单里插入 CSRF Token

<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

如果用的是 Blade 模板引擎,应该这样:

<input type="hidden" name="_token" value="{{ csrf_token() }}">

你不需要手工去确认在 POST,PUT,或者 DELETE 请求上的 CSRF token 。VerifyCsrfToken HTTP middleware 会去验证在请求里的 token 是否匹配存储在用户会话里的 token 。

方法欺骗

HTML 的表单并不支持 PUT 还有 DELETE 动作。所以在为表单定义 PUT 或者 DELETE 路由的时候,你需要在表单里用一个隐藏的 _method 字段。这个字段里的值就是使用的 HTTP 请求的方法,比如:

<form action="https://ninghao.net/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
</form>

上面的 _method 字段的值是 PUT,这样这个表单在提交的时候,就会使用 PUT 这种 HTTP 的方法。PUT 的意思就是要去修改东西,DELETE 的意思是去删除。

路由参数

你可以获取到请求 URI 里面的某一段东西:

基本的路由参数

Route::get('user/{id}', function($id)
{
    return 'User '.$id;
});

{id} 就是地址里的参数,比如用户在用 GET 方法请求 user/1 这个地址的时候,这个 {id} 参数的值就会是 1 ,这个参数的值作为路由里的匿名函数的一个参数传递进来,用 $id 来表示这个参数的值,也就是,如果用户请求 user/1 ,返回的东西就是 User 1 。

可选的路由参数

Route::get('user/{name?}', function($name = null)
{
    return $name;
});

{name?},这个参数里用了一个 ? 号,表示这是一个可选的参数。这样用户可以访问 /user 这个地址,也可以访问 /user/wanghao,/user/xiaoxue 这样的地址,如果是这样,这个路由会返回参数的值,也就是 wanghao 或者 xiaoxue 。

带默认值的可选路由参数

Route::get('user/{name?}', function($name = 'John')
{
    return $name;
});

$name = 'John' 指定了参数默认的值是 John ,如果访问的地址里不带参数,这个路由就会返回 John 。

用正则表达式约束参数的类型

Route::get('user/{name}', function($name)
{
    //
})
->where('name', '[A-Za-z]+');

Route::get('user/{id}', function($id)
{
    //
})
->where('id', '[0-9]+');

在上面定义的第一个路由里,{name} 这个参数的值的类型必须是字符类型的值,从 A 到 Z ,或者 a 到 z 这样的值。因为这个路由里,用了一个 where 方法,为参数 name 设置了一种匹配的模式,规定了这个参数的值的类型。

第二个路由里 {id} 这个参数的值必须是数字,就是从 0 到 9 这样的数字。如果访问 user/wanghao,会报错,因为参数 {id} 的值是 wanghao,这并不是一个数字类型的值 。

传递一个约束的数组

Route::get('user/{id}/{name}', function($id, $name)
{
    //
})
->where(['id' => '[0-9]+', 'name' => '[a-z]+'])

意思是分别限定一下 {id} 参数还有 {name} 参数的值的类型。

定义全局模式

如果你打算用正则表达式在全局范围内去约束路由参数,可以使用 pattern 方法。在 RouteServiceProvider 里的 before 方法上去定义这些模式。

$router->pattern('id', '[0-9]+');

一旦定义了这些模式,会应用在所有的路由参数上:

Route::get('user/{id}', function($id)
{
    // {id} 参数必须是数字类型的值
});

访问路由参数里的值

使用 input 方法,可以在路由以外的地方得到路由参数的值:

if ($route->input('id') == 1)
{
    //
}

通过 Illuminate\Http\Request 这个实例可以得到当前路由参数。当前请求的请求实例可以通过 Request 这个 facade 得到,或者在依赖注入的地方 type-hinting Illuminate\Http\Request :

use Illuminate\Http\Request;

Route::get('user/{id}', function(Request $request, $id)
{
    if ($request->route('id'))
    {
        //
    }
});

命名路由

命名路由就是给路由起个名字,这样可以很方便的生成 URL 或者重定向到一个指定的路由上。使用 as 数组键可以为路由起名字:

Route::get('user/profile', ['as' => 'profile', function()
{
    //
}]);

你也需要为控制器动作指定路由的名字:

Route::get('user/profile', [
    'as' => 'profile', 'uses' => 'UserController@showProfile'
]);

现在,你就可以在生成 URL 或者重定向的时候使用路由的名字了:

$url = route('profile');

$redirect = redirect()->route('profile');

currentRouteName 方法可以返回处理当前请求用到的路由的名字:

$name = Route::currentRouteName();

路由群组

有时候你打算在一组群组上使用一个过滤器,不需要为每个路由去指定过滤器,你可以使用路由群组:

Route::group(['middleware' => 'auth'], function()
{
    Route::get('/', function()
    {
        // 应用了 Auth 过滤器
    });

    Route::get('user/profile', function()
    {
        // 应用了 Auth 过滤器
    });
});

你可以在 group 数组上使用 namespace 参数来指定命名空间:

Route::group(['namespace' => 'Admin'], function()
{
    //
});

注意:默认情况下,在你的 routes.php 文件里的 RouteServiceProvider 会带一个命名空间的群组,允许你在注册控制器路由的时候,不需要指定全部的命名空间。

子域名路由

Laravel 可以处理 wildcard 子域名,会传递来自域名的 wildcard 参数。

定义子域名路由

Route::group(['domain' => '{account}.myapp.com'], function()
{

    Route::get('user/{id}', function($account, $id)
    {
        //
    });

});

路由前缀

使用在 group 里的属性数组的 prefix 选项,可以为一个路由群组设置一个前缀。

Route::group(['prefix' => 'admin'], function()
{

    Route::get('user', function()
    {
        //
    });

});

路由模型绑定

路由模型绑定提供了一种方便的方法,可以把类的实例注入到路由里面。比如你不需要只注入用户的 ID ,你可以注入整个 User 类的实例匹配给定的 ID 。

首先,使用路由的 model 方法,为给定的参数指定类(class)。你需要在 RouteServiceProvider::boot 方法上去定义模型绑定:

把一个参数绑定到一个模型上

public function boot(Router $router)
{
    parent::boot($router);

    $router->model('user', 'App\User');
}

然后,去定义一个包含 {user} 参数的路由:

Route::get('profile/{user}', function(App\User $user)
{
    //
});

把 {user} 参数绑定到了 App\User 模型以后,这样一个 User 实例就会被注入到路由里面。比如,请求的是 profile/1 ,就将会注入一个 ID 号是 1 的 User 的实例。

注意:如果在数据库里没找到匹配的模型实例,会扔出一个 404 的错误。

如果你想指定自己的 “ not found” ,可以传递一个 Closure 作为 model 方法的第三个参数:

Route::model('user', 'User', function()
{
    throw new NotFoundHttpException;
});

如果你想使用自己的 resolution 逻辑,可以使用 Router::bind 方法。传递给 bind 方法的 Closure 会接收到 URL 片段上的值,你要返回一个要注入到路由里的类的实例:

Route::bind('user', function($value)
{
    return User::where('name', $value)->first();
});

抛出 404 错误

有两种在路由上触发 404 错误的方法。第一种是可以使用 abort 帮手:

abort(404);

abort 帮手只会简单的抛出一个带特定状态码的 Symfony\Component\HttpFoundation\Exception\HttpException 。

第二种方法是可以手工抛出一个 Symfony\Component\HttpKernel\Exception\NotFoundHttpException. 的实例。

Laravel Laravel5 中文手册

评论

就是存放地址变了,其他倒是和4没啥差别

不对,少说了,5多了个controllers

Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);

浩哥:
laravel 路由 post 提交问题
TokenMismatchException in VerifyCsrfToken.php line 53:

用postman get 提交的就好使
用postman post 提交的就报错,期间也做了一个模拟的 表单 还是没效果
请问这是什么原因造成的。

微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

14696
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点