Laravel中所有路由定义在/app/Http/routes.php
文件中,该文件默认定义了应用的首页路由:
Route::get('/', function () { return view('welcome'); });
这段代码的意思是:当访问应用首页http://selfstudy.com的时候,返回/resources/views/welcome.blade.php
视图中的内容并渲染到浏览器页面中:
Route::get('/testPost',function(){ $csrf_token = csrf_token(); $form = <<<FORM <form action="/hello" method="POST"> <input type="hidden" name="_token" value="{$csrf_token}"> <input type="submit" value="Test"/> </form> FORM; return $form; }); Route::post('/hello',function(){ return "Hello Laravel[POST]!"; });
首先我们定义一个/testPost
页面用于提交POST请求表单,在http://selfstudy.com/testPost
页面点击“Test”按钮,页面跳转到http://selfstudy.com/hello并显示:
Hello Laravel[POST]!
Route::match(['get','post'],'/hello',function(){ return "Hello Laravel!"; });
当然还使用更方便的any
方法匹配所有请求方式:
Route::any('/hello',function(){ return "Hello Laravel!"; });
效果都一样。
Route::get('/hello/{name}',function($name){ return "Hello {$name}!"; });
在浏览器中访问http://selfstudy.com/hello/yyyyk输出:
Hello yyyyk
当然还可以指定多个参数:
Route::get('/hello/{name}/by/{user}',function($name,$user){ return "Hello {$name} by {$user}!"; });
这样在浏览器中访问http://selfstudy.com/hello/yyyyk/by/A
则会输出:
Hello yyyyk by A!
注意以上参数是必选的,如果没有输入参数会抛出MethodNotAllowedHttpException
或NotFoundHttpException
异常。
此外闭包函数中的参数与路由参数一一对应。
有时候我们并不总是想要输入对应参数,我们通过这种方式来定义:
Route::get('/hello/{name?}',function($name="yyk"){ return "Hello {$name}!"; });
我们同时为可选参数指定了默认值,这样当我们访问http://selfstudy.com/hello时输出:
Hello yyk!
当我们访问http://selfstudy.com/hello/yykkk
的时候输出:
Hello yykkk!
有时候我们希望对路由有更加灵活的条件约束,可以通过正则表达式来实现:
Route::get('/hello/{name?}',function($name="Yykk"){ return "Hello {$name}!"; })->where('name','[A-Za-z]+');
该条件约束意味着$name
参数只能包含大小写字母,如果包含数字或中文就会抛出NotFoundHttpException
异常。
如果我们想要在全局范围内对参数进行条件约束,可以在RouteServiceProvider
的boot
方法中做如下定义:
public function boot(Router $router) { $router->pattern('name','[A-Za-z]+'); parent::boot($router); }
我们访问http://selfstudy.com/hello/yy123时一样会抛出
NotFoundHttpException
异常。这意味着boot
方法定义的参数条件约束将会应用到所有包含该参数的路由中。
我们使用as关键字为路由命名
Route::get('/test/routename',['as'=>'name', function(){ return 'Hello Routename!'; }]);
路由命名可以让我们在使用route
函数生成指向该路由的URL或者生成跳转到该路由的重定向链接时更加方便:
Route::get('/testNamedRoute',function(){ return route('name'); });
我们在浏览器中访问http://selfstudy.com/testNamedRoute时输出http://selfstudy.com/testNamedRoute,然后我们修改上述闭包内代码:
Route::get('/testNamedRoute',function(){ return redirect()->route('name'); });
再次在浏览器中访问http://selfstudy.com/testNamedRoute
时会跳转到http://selfstudy.com/test/routename。并且输出Hello Routename!
我们甚至还可以在使用带参数的路由命名:
Route::get('/hello/routename/{id}',['as'=>'name',function($id){ return 'Hello routename'.$id.'!'; }]);
对应的测试路由定义如下:
Route::get('/testNamedRoute',function(){ return redirect()->route('name',['id'=>1]); });
这样,当我们在浏览器中访问http://selfstudy.com/testNamedRoute
时会跳转到http://selfstudy.com/test/routename/1
再来看一个更复杂的例子,使用路由分组时如何定义路由命名?官网文档提供的例子如下:
Route::group(['as' => 'admin::'], function () { Route::get('dashboard', ['as' => 'dashboard', function () { // }]); });
在Route
门面的group
方法中使用一个as关键字来指定该路由群组中所有路由的公共前缀,然后在里面每个路由中使用as
关键字为该路由命名。
这样我们可以通过如下方式来生成该路由URL:
Route::get('/testNamedRoute',function(){ return route('admin::dashboard'); });
路由分组就是将一组拥有相同属性(中间件、命名空间、子域名、路由前缀等)的路由使用Route
门面的group
方法聚合起来
默认情况下,routes.php
中的定义的控制器位于App\Http\Controllers
命名空间下,所以如果要指定命名空间,只需指定App\Http\Controllers
之后的部分即可:
Route::group(['namespace' => 'Test'], function(){
// 控制器在 "App\Http\Controllers\Test" 命名空间下
Route::group(['namespace' => 'Files'], function()
{
// 控制器在 "App\Http\Controllers\Test\
Files" 命名空间下
});
});
如果路由群组中的所有路由包含统一前缀,则我们可以通过在group
方法中设置prefix
属性来指定该前缀:
Route::group(['prefix'=>'test'],function(){ Route::get('write',function(){ return "Write test"; }); Route::get('update',function(){ return "Update test"; }); });
这样我们就可以通过http://selfstudy.com/test/write
或者
来访问对应的操作。
/updatehttp://selfstudy.com/test
我们甚至还可以在路由前缀中指定参数:
Route::group(['prefix'=>'test/{num}'],function(){ Route::get('write',function($num){ return "Write Test{$num}"; }); Route::get('update',function($num){ return "Update Test{$num}"; }); });
这样我们在浏览器中访问
,则对应会输出:
test/5.1/writehttp://selfstudy.com/
Write Test 5.1
首先我们在应用根目录下运行如下Artisan命令生成一个测试用的中间件TestMiddleware
:
打开命令行 win+R 到项目根目录(也就是artisan命令所在目录)执行以下命令
php artisan make:middleware TestMiddleware
这样会在/app/Http/Middleware
目录下生成一个TestMiddleware.php
文件,打开该文件编辑TestMiddleware
类的handle
方法如下:
public function handle($request, Closure $next) { if($request->input('age')<18) return redirect()->route('refuse'); return $next($request); }
我们在中间件中定义这段业务逻辑的目的是年龄18岁以下的未成年人不能访问。
然后我们打开/app/Http/Kernel.php
文件,新增TestMiddleware
到Kernel
的$routeMiddleware
属性:
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'test' => \App\Http\Middleware\TestMiddleware::class, ];
接下来我们在routes.php
中定义路由如下:
Route::group(['middleware'=>'test'],function(){ Route::get('/write/middleware',function(){ //使用Test中间件 }); Route::get('/update/middleware',function(){ //使用Test中间件 }); }); Route::get('/age/refuse',['as'=>'refuse',function(){ return "未成年人禁止入内!"; }]);
这样当我们在浏览器中访问http://selfstudy.com/write/middleware?age=15
或者http://selfstudy.com/update/middleware?age=15
时就会跳转到http://selfstudy.com
/age/refuse
,并显示:
未成年人禁止入内!