Laravel 应用的入口:路由系列之参数、命名和分组篇

路由参数

必选参数

有时我们需要在路由中获取 URI 请求参数。例如,如果要从 URL 中获取用户ID,需要通过如下方式定义路由参数:

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

可以根据需要在路由中定义多个路由参数:

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    return $postId . '-' . $commentId;
});
{}-_{post-id}{post_id}

可选参数

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

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});
http://blog.dev/userJohn

正则约束

wherewhere
Route::get('user/{name}', function ($name) {
    // name 必须是字母且不能为空
})->where('name', '[A-Za-z]+');

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

Route::get('user/{id}/{name}', function ($id, $name) {
    // 同时指定 id 和 name 的数据格式
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
user/{id}user/{name}

全局约束

patternRouteServiceProviderboot
/**
 * 定义路由模型绑定,模式过滤器等
 *
 * @param  \Illuminate\Routing\Router  $router
 * @return void
 * @translator  https://xueyuanjun.com
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');
    parent::boot();
}

一旦模式被定义,将会自动应用到所有包含该参数名的路由中:

Route::get('user/{id}', function ($id) {
    // 只有当 {id} 是数字时才会被调用
});

除此之外,该模式还会被应用到诸如下面这些路由参数上:

Route::get('post/{id}', function ($id) {
    // 只有当 {id} 是数字时才会被调用
});

Route::get(`product/{id}', function ($id) {
    // 只有当 {id} 是数字时才会被调用
});

很显然这种方式让代码更简洁,也为我们实现同一参数统一约束带来了方便。

命名路由

name
Route::get('user/profile', function () {
    // 通过路由名称生成 URL
    return 'my url: ' . route('profile');
})->name('profile');

还可以为控制器动作指定路由名称:

Route::get('user/profile', 'UserController@showProfile')->name('profile');

这样我们就可以通过以下方式定义重定向:

Route::get('redirect', function() {
    // 通过路由名称进行重定向
    return redirect()->route('profile');
});

为命名路由生成 URL

route
$url = route('profile');
route
Route::get('user/{id}/profile', function ($id) {
    $url = route('profile', ['id' => $id]);
    return $url;
})->name('profile');
http://blog.dev/user/123/profilehttp://blog.dev/user/123/profile

检查当前路由

named
/**
 * 处理输入请求
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

路由分组

Route::group

中间件

middleware
Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

关于中间件的使用我们在后面单独讲中间件时再进行示例演示,这里我们先了解这样使用就行。

命名空间

namespace
Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});
RouteServiceProviderApp\Http\ControllersApp\Http\Controllers

关于命名空间后面我们单独讲控制器的时候还会再详细演示,这里先了解用法即可。

子域名路由

domain
Route::domain('{account}.blog.dev')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        return 'This is ' . $account . ' page of User ' . $id;
    });
});
account.blog.devhttp://account.blog.dev/user/11
This is account page of User 1

路由前缀

prefixadmin
Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});
http://blog.dev/admin/users