gpt4 book ai didi

Laravel学习教程之路由模块

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Laravel学习教程之路由模块由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

前言 。

本文主要给大家介绍的是关于laravel路由模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧.

备注:本文是基于laravel 5.4版本的路由模块代码进行分析书写; 。

模块组成 。

下图展示了路由模块中各个文件的关系,并进行简要说明; 。

Laravel学习教程之路由模块

剖析 。

服务提供者 。

看laravel模块,首先找serviceprovider文件,这是模块与ioc容器交互的入口,从这个文件,可以看出该模块提供向系统提供了哪些服务; 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function register() {
  // 注册路由管理,提供路由注册,路由匹配的功能
  $this ->registerrouter();
  // 注册 url 生成器实例
  $this ->registerurlgenerator();
  // 注册跳转器
  $this ->registerredirector();
  // 绑定 psr-7 请求实现到 serverrequestinterface 接口
  $this ->registerpsrrequest();
  // 绑定 psr-7 response 实现到 responseinterface 接口
  $this ->registerpsrresponse();
  // 注册 reponsefactory,提供各式各样的 response,比如视图响应、json响应、jsonp响应、文件下载等
  $this ->registerresponsefactory();
}

路由管理 。

“路由管理”服务有以下元素需要了解:

  • route:路由;会记录 url、http 动作、action (路由要执行的具体对象,可能是 closure,也可以是某个 controller 中的方法),路由参数,路由参数的约束;
  • routecollection:路由集,用来存储所有route对象的“盒子”;
  • routegroup:路由组;只有路由注册过程中会临时用到;存储一批路由公共的一些属性,属性包括domain、prefix、as、middleware、namespace、where;
  • resource:资源路由;资源路由是一套路由的统称,包含列表(index)、显示增加(create)、保存增加(store)、显示详情(show)、显示编辑详情(edit)、更新编辑(update)、删除详情(destory);同时可以通过调用only或except方法或参数的形式只生成部分路由;
  • action:路由要执行的对象;有两种表现形式,一是closure函数,二是类似['uses' => 'foocontroller@method', 'as' => 'name']这样的字符串;对于不同的表现形式,路由在执行时会调用不同的处理;

注册流程 。

在项目启动后,会执行所有serviceprovider的loadroutes方法,也就是调用map方法,一般情况下map方法如下 。

?
1
2
3
public function map(router $router ){
  require __dir__. '/routes.php' ;
}

这时候,项目就会执行很多route::get、route::post、route::group方法; 。

当遇到route::group方法时,会实例化一个routegroup对象,put进router管理类的路由组栈头部;而后当执行get、post这类具体的注册路由方法时,会把当前路由组栈中所有组的属性合并进新路由中,将新路由存储在routecollection这个大盒子里;当route::group的closure执行完毕时,会把头部的routegroup实例pull出去; 。

当执行route::resource时,router管理类会调用resourceregister类来完成批量注册路由; 。

对于 router::get这类注册方法,illuminate\foudation\helpers提供了简写; 。

  • router::get 简化成 get,
  • router::post 简化成 post,
  • router::put 简化成 put,
  • router::patch 简化成 patch,
  • router::delete 简化成 delete,
  • router::resource简化成 resource,

至此,routecollection大盒子就存放了所有要注册的路由; 。

request 请求匹配流程 。

首先,request请求会经过foundation/http/kernel的handle方法,在这个方法中,请求会执行以下语句 。

?
1
$this ->router->dispatch( $request )

这里的$this->router,就是router管理类;dispatch方法如下 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public function dispatch(request $request ) {
  $this ->currentrequest = $request ;
  return $this ->dispatchtoroute( $request );
}
 
public function dispatchtoroute(request $request ) {
  // 根据请求的 url 找到匹配的路由
  $route = $this ->findroute( $request );
  // 将路由绑定到请求上
  $request ->setrouteresolver( function () use ( $route ) {
  return $route ;
  }
  // 触发 routematched 事件
  $this ->events->dispatch( new events\routematched( $route , $request ));
  // 通过 pipeline 流水线执行路由上绑定的中间件及对应的方法
  $response = $this ->runroutewithinstack( $route , $request );
  // 根据 request 请求设置 response 的响应头
  return $this ->prepareresponse( $request , $response );
}

1、根据请求找匹配的路由 。

`routecollection`根据请求的`http`动作缩小要匹配的路由范围;在筛选出来的这些路由中依次遍历,找出第一个符合验证的路由(需要进行较验的验证在`route`中的`getvalidators`方法中声明); 。

2、将路由绑定到请求上 。

3、触发routematched事件 。

初始化的`laravel`项目没有对`routematched`路由匹配事件进行任何的监听器绑定,如有需要,可以自定义监听器,在模块的`eventserviceprovider`中注册该事件监听;这样一旦请求匹配上某个路由,就可以执行自定义方法了; 。

4、通过 pipeline 流水线执行路由上绑定的中间件及对应的方法 。

在`runroutewithinstack`方法中,系统会判断是否需要执行中间件,如果`ioc`容器中设置了`middleware.disable`的值为`true`,则需要执行的中间件数组为空;否则会找到所有的中间件,并按照`middlewarepriority`对必要的一些中间件进行排序调整;然后执行`$route->run()`方法; 。

5、根据 request 请求设置 response 的响应头 。

项目中会用到的一些方法 。

  • 获取路由集合 app('router')->getroutes()
  • 获取当前的请求 $request = app('router')->getcurrentrequest()
  • 获取当前请求所对应的路由 $route = $request->route() 或 $route = app('router')->getcurrentroute()
  • 获取当前路由需要执行的中间件 $middlewares = app('router')->gatherroutemiddleware($route)

url 生成器 。

url 生成器是什么?

举个例子, 。

?
1
2
3
4
5
6
$url = new urlgenerator(
  $routes = new routecollection,
  $request = request::create( 'http://www.foo.com/' )
);
 
$url ->to( 'foo/bar' ); // 输出 http://www.foo.com/foo/bar

像这种基于当前请求,生成指定路径的url; 。

这部分功能由两个文件完成,一个是urlgenerator.php,另一个是routeurlgenerator.php;urlgenerator.php处理根据路径名生成url,routeurlgenerator.php处理根据路由生成url; 。

列一些常用的使用:

根据路径名生成 。

使用to方法,第一个参数为路径,第二个参数是数组,implode后会接着路径名,第三个参数决定用不用https 。

?
1
2
3
4
5
6
7
8
9
// 路径名是 foo/bar,当前请求的根路径为 http://www.foo.com,所以输出是 http://www.foo.com/foo/bar
$url ->to( 'foo/bar' )
// 路径名是 foo/bar,当前请求的根路径为 http://www.foo.com,第三个参数决定 scheme 是 https,所以输出是 https://www.foo.com/foo/bar
$url ->to( 'foo/bar' , [], true)
// 路径名是 foo/bar,第二个参数 是补充路径名,implode 后是 /baz/boom
// 第三个参数决定 scheme 是 https,所以输出是 https://www.foo.com/foo/bar/baz/boom
$url ->to( 'foo/bar' , [ 'baz' , 'boom' ], true)
// 路径名是 foo/bar,查询参数是 ?foo=bar ,补充路径是 /baz,所以输出是 https://www.foo.com/foo/bar/baz?foo=bar
$url ->to( 'foo/bar?foo=bar' , [ 'baz' ], true)

根据路由的 as 名生成 。

使用route方法,第一个参数为指定路由的 as 名,第二个参数是参数数组,第三个参数决定是否显示根目录(默认为 true) 。

?
1
2
3
4
5
6
7
8
9
10
11
12
$route = new route([ 'get' ], 'foo/bar' , [ 'as' => 'foo' ]);
$routes ->add( $route );
 
// 输出 'http://www.foo.com/foo/bar
$url ->route( 'foo' );
 
// 第三个参数为 false,表示不显示根目录,于是输出 /foo/bar
$url ->route( 'foo' , [], false)
 
// 路由中的 url 本身不带参数,则第二参数中所有关联数组都将作为查询参数
// 输出 /foo/bar?foo=bar
$url ->route( 'foo' , [ 'foo' => 'bar' ], false)
?
1
2
3
4
5
6
7
8
9
10
$route = new route([ 'get' ], 'foo/bar/{baz}/breeze/{boom}' , [ 'as' => 'bar' ]);
$routes ->add( $route );
 
// 路由上的 url 带参数,根据参数名找值;剩余多余的为查询参数;
// 输出 http://www.foo.com/foo/bar/otwell/breeze/taylor?fly=wall
$url ->route( 'bar' , [ 'boom' => 'taylor' , 'baz' => 'otwell' , 'fly' => 'wall' ]);
 
// 路由上的 url 带参数,找不到对应的参数值,则按顺序作值;剩余多余的为查询参数;
// 输出 http://www.foo.com/foo/bar/taylor/breeze/otwell?fly=wall
$url ->route( 'bar' , [ 'taylor' , 'otwell' , 'fly' => 'wall' ]);

根据路由的 action 名生成 。

使用action方法,第一个参数为指定路由的 action 名,第二个参数是参数数组,第三个参数决定是否显示根目录(默认为 true) 。

?
1
2
3
4
5
$route = new route([ 'get' ], 'foo/bam' , [ 'controller' => 'foo@bar' ]);
$routes ->add( $route );
 
// 输出 http://www.foo.com/foo/bam
$url ->action( 'foo@bar' );
?
1
2
3
4
5
$route = new route([ 'get' ], 'foo/invoke' , [ 'controller' => 'invokableactionstub' ]);
$routes ->add( $route );
 
// 输出 http://www.foo.com/foo/invoke
$url ->action( 'invokableactionstub' );

设置全局默认参数 。

?
1
2
3
4
5
6
$url ->defaults([ 'locale' => 'en' ]);
 
$route = new route([ 'get' ], 'foo' , [ 'as' => 'defaults' , 'domain' => '{locale}.example.com' , function () {}]);
 
// 路由 url 有参数,但没有传参数值,则会找全局默认参数值;输出 http://en.example.com/foo
$url ->route( 'defaults' );

设置全局命名空间 。

这样调用的时候,不用在 action 上省略这部分命名空间 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 设置全局命名空间
$url ->setrootcontrollernamespace( 'namespace' );
 
// 配置添加路由
$route = new route([ 'get' ], 'foo/bar' , [ 'controller' => 'namespace\foo@bar' ]);
$routes ->add( $route );
$route = new route([ 'get' ], 'foo/invoke' , [ 'controller' => 'namespace\invokableactionstub' ]);
$routes ->add( $route );
 
// 输出 http://www.foo.com/foo/bar; action 的值省略 namespace 这个命名空间
$url ->action( 'foo@bar' );
// 输出 http://www.foo.com/foo/invoke; action 的值省略 namespace 这个命名空间
$url ->action( 'invokableactionstub' );
 
// 配置添加路由
$route = new route([ 'get' ], 'something/else' , [ 'controller' => 'something\foo@bar' ]);
$routes ->add( $route );
 
// 输出 http://www.foo.com/something/else; action 的最前面加了 `\`,全局命名空间下调用
$url ->action( '\something\foo@bar' );

跳转器 。

跳转器内部提供了以下跳转; 。

home 。

通过调用app('redirect')->home()会跳转至根目录下\; 。

?
1
public function home( $status = 302)

back 。

通过调用app('redirect')->back()会跳转至上一次访问页面;或者全局帮助函数back()也可以; 。

?
1
public function back( $status = 302, $headers = [], $fallback = false)

第三个参数表示,如果没有前一次访问请求,访问哪个页面,具体源码如下:

?
1
2
3
4
5
6
7
if ( $url ) {
   return $url ;
} elseif ( $fallback ) {
  return $this ->to( $fallback );
} else {
  return $this ->to( '/' );
}

refresh 。

通过调用app('redirect')->refresh()会刷新当前访问页面; 。

?
1
public function refresh( $status = 302, $headers = [])

to 。

通过调用app('redirect')->to('path')会跳转至指定路径页面;或者全局帮助函数redirect('path')也可以; 。

这里的 path 路径是不包含根目录的,例如(foo/bar); 。

?
1
public function to( $path , $status = 302, $headers = [], $secure = null)

第四个参数表示是否使用https; 。

away 。

通过调用app('redirect')->away('path')会跳转至指定路径页面; 。

这里的 path 路径是包含根目录的,例如(http://xx.com/foo/bar); 。

?
1
public function away( $path , $status = 302, $headers = [])

secure 。

通过调用app('redirect')->secure('path')会跳转至指定路径页面;这里的path路径是不包含根目录的; 。

?
1
public function secure( $path , $status = 302, $headers = [])

其本质是调用了to方法 。

?
1
return $this ->to( $path , $status , $headers , true);

route 。

通过调用app('redirect')->route('route_as_name') ,根据路由的as名会跳转至与路由一致的url路径页; 。

?
1
public function route( $route , $parameters = [], $status = 302, $headers = [])

action 。

通过调用app('redirect')->action('route_action') ,根据路由的action名会跳转至与路由一致的url路径页; 。

?
1
public function action( $action , $parameters = [], $status = 302, $headers = [])

guest 。

跳到指定的路径页的同时,将当前url存放至session中,键名为url.intended,

?
1
public function guest( $path , $status = 302, $headers = [], $secure = null)

intended 。

跳转至session中键名为url.intended的值所对应的url;如果不存在,则跳转至第一个参数所传的值; 。

?
1
public function intended( $default = '/' , $status = 302, $headers = [], $secure = null)

响应工厂(responsefactory) 。

responsefactory文件提供了两部分 api,分别是与响应类型相关和与跳转相关; 。

响应 。

response()会返回responsefactory实例; 。

视图响应 。

?
1
response()->view( 'hello' , $data , 200);

jsop响应 。

?
1
response()->json([ 'name' => 'abigail' , 'state' => 'ca' ]);

jsonp响应 。

?
1
response()->json([ 'name' => 'abigail' , 'state' => 'ca' ])->withcallback( $request ->input( 'callback' ));

文件响应 。

直接在浏览器显示文件,而不是下载,例如图片或pdf;file方法第一参数为文件路径,第二参数选填为头信息数组; 。

?
1
response()->file( $pathtofile , $headers );

文件下载 。

download方法第一参数为文件路径,第二参数选填为文件名,第三参数选填为头信息数组; 。

?
1
return response()->download( $pathtofile , $name , $headers );

跳转 。

这里的跳转方法,其实调用的还是跳转器中的方法,不过是在暴露更多的接口,方便调用与使用; 。

  。

方法名 调用 实际调用的是跳转器中的哪个方法
redirectto response()->redirectto(...) to方法
redirecttoroute response()->redirecttoroute(...) route方法
redirecttoaction response()->redirecttoaction(...) action方法
redirectguest response()->redirectguest(...) guest方法
redirecttointended response()->redirecttointended(...) intended方法

  。

总结 。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我的支持.

原文链接:https://segmentfault.com/a/1190000010440480 。

最后此篇关于Laravel学习教程之路由模块的文章就讲到这里了,如果你想了解更多关于Laravel学习教程之路由模块的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com