欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

laravel 路由

程序员文章站 2022-03-06 13:11:29
...

路由

什么是路由?

路由不是你家里的路由器,是URL与函数直接的关系映射。

参考手册 路由

HTTP 常用请求方式

  1. get 向特定的路径资源发出请求
  2. post 向指定路径资源提交数据进行处理请求(一般用于提交表单或者上传文件)
  3. put 客户端向服务器传送的数据取代指定的文档的内容,用于修改
  4. patch 局部信息修改
  5. delete 请求服务器删除指定的数据
  6. options 返回服务器针对特定资源所支持的HTTP请求方法

路由准许注册的相应

所有 Laravel 路由都定义在路由文件中,这些文件位于 routes 目录下。

  1. Route::get($uri, $callback);
  2. Route::post($uri, $callback);
  3. Route::put($uri, $callback);
  4. Route::patch($uri, $callback);
  5. Route::delete($uri, $callback);
  6. Route::options($uri, $callback);

这些路由被分配给 web 中间件组, 该组提供会话状态和 CSRF 保护等功能。

  • 基本路由

    最基本的 Laravel 路由接受一个 URI 和一个闭包,它提供了一种非常简单和有表现力的方法来定义路由和行为,而不需要复杂的路由配置文件:

  1. use Illuminate\Support\Facades\Route;
  2. Route::get('/greeting', function () {
  3. return 'Hello World';
  4. });
  • 默认路由文件
  1. Route::get('/user', [UserController::class, 'index']);
  • 重定向路由
  1. Route::redirect('/here', '/there');

默认情况, Route::redirect 返回的状态码是 302 。 但你可以使用第三个可选参数自定义状态码:

  1. Route::redirect('/here', '/there', 301);
  • 视图路由

如果你的路由只需要返回一个 view,你可以使用 Route::view 方法。 像 redirect 方法一样, 此方法提供了一个简单的快捷方式,因此您不必定义完整的路由或控制器。 该 view 方法接受 URI 作为其第一个参数,并接受视图名称作为其第二个参数。另外,您可以提供一个数据数组作为可选的第三个参数传递给视图:

  1. Route::view('/welcome', 'welcome');
  2. Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

有的时候你可能需要注册一个可响应多个 HTTP 请求的路由,这时你可以使用 match 方法,也可以使用 any 方法注册一个实现响应所有 HTTP 请求的路由:

  1. Route::match(['get', 'post'], '/', function () {
  2. //支持两种方法
  3. });
  4. Route::any('foo', function () {
  5. //可以接收所有的方法
  6. });
  • 路由参数

必填参数

有时您将需要捕获路由内的 URI 段。例如,您可能需要从 URL 中捕获用户的 ID。您可以通过定义路由参数来做到这一点:

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

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

  1. Route::get('/posts/{post}/comments/{comment}', function ($postId, $commentId) {
  2. //
  3. });

可选参数

有时,你可能需要指定一个路由参数,但你希望这个参数是可选的。你可以在参数后面加上 ? 标记来实现,但前提是要确保路由的相应变量有默认值:

  1. Route::get('/user/{name?}', function ($name = null) {
  2. return $name;
  3. });
  4. Route::get('/user/{name?}', function ($name = 'John') {
  5. return $name;
  6. });

正则表达式约束

你可以使用路由实例上的 where 方法约束路由参数的格式。where 方法接受参数名称和定义参数应如何约束的正则表达式:

  1. Route::get('/user/{name}', function ($name) {
  2. //
  3. })->where('name', '[A-Za-z]+');
  4. Route::get('/user/{id}', function ($id) {
  5. //
  6. })->where('id', '[0-9]+');
  7. Route::get('/user/{id}/{name}', function ($id, $name) {
  8. //
  9. })->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

路由命名

路由命名可以方便地为指定路由生成 URL 或者重定向。通过在路由定义上链式调用 name 方法可以指定路由名称:

  1. Route::get('/user/profile', function () {
  2. //
  3. })->name('profile');

注意:路由命名必须是唯一的

生成指定路由的 URL

一旦为路由指定了名称,你可以在生成 url 或者通过 Laravel 的 routeredirect 辅助函数重定向时使用路由的名字:

  1. // 生成链接...
  2. $url = route('profile');
  3. // 生成重定向...
  4. return redirect()->route('profile');

如果有定义参数的命名路由,可以把参数作为 route 函数的第二个参数传入,指定的参数将会自动插入到 URL 中对应的位置:

  1. Route::get('/user/{id}/profile', function ($id) {
  2. //
  3. })->name('profile');
  4. $url = route('profile', ['id' => 1]);

如果在数组中传递其他参数,这些键或值对将自动添加到生成的 URL 查询字符串中:

  1. Route::get('/user/{id}/profile', function ($id) {
  2. //
  3. })->name('profile');
  4. $url = route('profile', ['id' => 1, 'photos' => 'yes']);
  5. // /user/1/profile?photos=yes

路由组

路由组允许你共享路由属性,例如中间件,这样不需要在每个单独的路由上定义那些属性。

嵌套组会尝试智能的 “合并” 他们的父组的属性。中间件和 “where” 条件会被合并,而名称和前缀会被追加。URI 前缀中的名称空间分隔符和斜杠会在适当的地方自动添加。

中间件

想把中间件分配给组内所有的路由,你可以在定义组之前使用 middleware 方法。中间件将按照它们在数组中列出的顺序执行:

  1. Route::middleware(['first', 'second'])->group(function () {
  2. Route::get('/', function () {
  3. // Uses first & second middleware...
  4. });
  5. Route::get('/user/profile', function () {
  6. // Uses first & second middleware...
  7. });
  8. });

子域路由

路由组也可以用来处理子域路由。子域可以像路由 uri 一样被分配路由参数,允许您捕获子域的一部分以便在路由或控制器中使用。 子域可以在定义组之前调用 domain 方法来指定:

  1. Route::domain('{account}.example.com')->group(function () {
  2. Route::get('user/{id}', function ($account, $id) {
  3. //
  4. });
  5. });

路由前缀

prefix 方法可以用给定的 URI 为组中的每个路由做前缀。例如,你可能想要在组内的所有路由 uri 前面加上 admin 前缀:

  1. Route::prefix('admin')->group(function () {
  2. Route::get('/users', function () {
  3. // Matches The "/admin/users" URL
  4. });
  5. });

路由名称前缀

name 方法可以用给定字符串作为组中的每个路由名的前缀。 例如,你可能想要用 admin 作为所有分组路由的前缀。因为给定字符串的前缀与指定的路由名完全一致,所以我们一定要提供末尾 . 字符在前缀中:

  1. Route::name('admin.')->group(function () {
  2. Route::get('/users', function () {
  3. // Route assigned name "admin.users"...
  4. })->name('users');
  5. });

路由缓存

将应用程序部署到生产环境时,应该利用 Laravel 的路由缓存。使用路由缓存将大大减少注册所有应用程序路由所花费的时间。要生成路由缓存,请执行 route:cache Artisan 命令:

  1. php artisan route:cache

运行此命令后,缓存的路由文件将在每个请求中加载。请记住,如果添加任何新路由,则将需要生成新的路由缓存。因此,route:cache 命令最好在生产环境运行。

您可以使用以下 route:clear 命令清除路由缓存:

  1. php artisan route:clear
  1. Route::get('/', function () {
  2. return view('welcome');
  3. });
  4. Route::get('/h', function () {
  5. return 'hello word';
  6. });
  7. Route::get('/user', function () {
  8. return 'user';
  9. });
  10. Route::get('/user/create', [UserController::class,'create']);
  11. Route::post('/user',[UserController::class,'store'] )->name('create');
  12. Route::get('/users', [UserController::class,'index']);
  13. Route::get('/users/{id}', [UserController::class,'show']);
  14. //Route::resource('/goods',GoodsController::class)->only(['index','show']);
  15. Route::resource('/goods',GoodsController::class)->except(['create','show']);
  16. //apiResource
  17. Route::redirect('/u','user',301);
  18. Route::match(['get','post'],'/getpost',function (){
  19. dd('getpost');
  20. });
  21. Route::any('/any',function (){
  22. dd('any');
  23. });
  24. //Route::get('/member/{id?}',function ($id){
  25. // return $id;
  26. //});
  27. //Route::get('/member/{id}/courses/{course}',function ($id,$course){
  28. // dd($id,$course);
  29. //})->where('id','[A-Za-z0-9]+');
  30. Route::get('/member/{id}/courses/{course}',function ($id,$course){
  31. dd($id,$course);
  32. })->where(['id'=>'[0-9]+','course'=>'[A-Za-z0-9]+']);
  33. Route::get('/member/{id}',function ($id){
  34. dd(route('member.show',['id'=>$id]));
  35. })->name('member.show');
  36. Route::get('/member',function (){
  37. return redirect()->route('member.show',['id'=>1]);
  38. });
  39. Route::post('upload',UploadController::class);
  40. Route::domain('api.lala.test')->name('admin.')->prefix('admin')->group(function (){
  41. Route::get('/user', function () {
  42. dd('admin/user');
  43. })->name('users');
  44. Route::get('/goods', function () {
  45. dd('admin/goods');
  46. })->name('goods');
  47. });
  48. //路由缓存
  49. //php artisan route:cache
  50. //清除缓存
  51. //php artisan route:clear
  52. //
  53. // php artisan route:list |grep list
  54. // php artisan make:controller GoodsController --resource
  55. // php artisan make:controller Home/UserController
  56. //php artisan make:controller PhotoController --resource --model=Photo

控制器

参考手册 控制器

我们要使用“控制器”的类来管理我们业务逻辑代码,而不是将所有请求处理逻辑定义为路由文件中的闭包。控制器可以将相关的请求处理逻辑分组到一个类中。例如,一个UserController类可能会处理所有与用户相关的传入请求,包括显示、创建、更新和删除用户。默认情况下,控制器存储在app/Http/Controllers目录中。

创建控制器

Laravel artisan 给我们提供了创建 Controller的命令,你只需执行下面代码

  1. php artisan make:controller UserController

他将会在 app/Http/Controllers这个目录下生成UserController

你可以在路由文件中添加上

  1. Route::get('profile', [UserController::class, 'show']);

接着可以在UserController中添加show方法,测试路由的和控制的连接。

通常在一个项目中,我们有前台和后台,在使用 php artisan make:controller的时候你可以,在控制器的前面添加目录名称来区分前后台,例:php artisan make:controller Admin/UserController 这样创建的控制器将会在app/Http/Controller/Admin目录下。

资源型控制器

如果说我们的控制器对应到每个模型上面,每个资源都有相同的操作,你会有 UserController或者GoodController,每个控制器中都会有对应的方法,获取列表、创建、删除、修改、查看、编辑页面、添加页面等。我们需要在路由中为每个控制的每个方法去创建对应的路由,并且在控制器创建不同的方法。我们需要统一这个方法名和路由创建的方式,例如:不可能在 UserController中获取列表我们叫list而在 GoodController 中我们叫 index ,在团队开发中这回产生歧义,我们可以使用下面命令快速创建一个控制器。

  1. php artisan make:controller UserController --resource

这个命令将会生成一个控制器 app/Http/Controllers/UserController.php。其中包括每个可用资源操作的方法。接下来,你可以给控制器注册一个资源路由:

  1. use App\Http\Controllers\UserController;
  2. Route::resource('users', UserController::class);

这个单一的路由声明创建了多个路由来处理资源上的各种行为。生成的控制器为每个行为保留了方法, 而且你可以通过运行 Artisan 命令 route:list 来快速了解你的应用程序。

请求方式 URI Action 路由名称
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{users} show users.show
GET /users/{users}/edit edit users.edit
PUT/PATCH /users/{users} update users.update
DELETE /users/{users} destroy users.destroy

指定资源模型

如果你使用了路由模型的绑定 路由模型绑定 并且想在资源控制器的方法中使用类型提示,你可以在生成控制器的时候使用 --model 选项:

  1. php artisan make:controller PhotoController --resource --model=Photo

部分资源路由

当声明资源路由时,你可以指定控制器处理的部分行为,而不是所有默认的行为:

  1. use App\Http\Controllers\PhotoController;
  2. Route::resource('photos', PhotoController::class)->only([
  3. 'index', 'show'
  4. ]);
  5. Route::resource('photos', PhotoController::class)->except([
  6. 'create', 'store', 'update', 'destroy'
  7. ]);

API 资源路由

当声明用于 APIs 的资源路由时,通常需要排除显示 HTML 模板的路由。例如 create and edit。为了方便起见 apiResource 方法自动排除这两个路由:

  1. use App\Http\Controllers\PhotoController;
  2. Route::apiResource('photos', PhotoController::class);

你也可以传递一个数组给 apiResources 方法来同时注册多个 API 资源控制器:

  1. use App\Http\Controllers\PhotoController;
  2. use App\Http\Controllers\PostController;
  3. Route::apiResources([
  4. 'photos' => PhotoController::class,
  5. 'posts' => PostController::class,
  6. ]);

要快速生成不包含 createedit 方法的用于开发接口的资源控制器,请在执行 make:controller 命令时使用 --api 参数:

  1. php artisan make:controller PhotoController --api

命名资源路由

默认情况下,所有的资源控制器行为都有一个路由名称。你可以传入 names 数组来覆盖这些名称:

  1. use App\Http\Controllers\PhotoController;
  2. Route::resource('photos', PhotoController::class)->names([
  3. 'create' => 'photos.build'
  4. ]);

命名资源路由参数

默认情况下,Route::resource 会根据资源名称的「单数」形式创建资源路由的路由参数。你可以在选项数组中传入 parameters 参数来轻松地覆盖每个资源。parameters 数组应该是资源名称和参数名称的关联数组:

  1. use App\Http\Controllers\AdminUserController;
  2. Route::resource('users', AdminUserController::class)->parameters([
  3. 'users' => 'admin_user'
  4. ]);

上面的示例将会为资源的 show 路由生成以下的 URL:

  1. /users/{admin_user}

补充资源控制器

如果你需要增加额外的路由到默认的资源路由之中,你需要在 Route::resource 前定义它们;否则,由 resource 方法定义的路由可能会无意间优先于你定义的路由:

  1. use App\Http\Controller\PhotoController;
  2. Route::get('/photos/popular', [PhotoController::class, 'popular']);
  3. Route::resource('photos', PhotoController::class);