- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Laravel学习教程之路由模块由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
本文主要给大家介绍的是关于laravel路由模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧.
备注:本文是基于laravel 5.4版本的路由模块代码进行分析书写; 。
模块组成 。
下图展示了路由模块中各个文件的关系,并进行简要说明; 。
剖析 。
服务提供者 。
看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();
}
|
路由管理 。
“路由管理”服务有以下元素需要了解:
['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的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在做一个关于代码学院的教程,我在这里收到一个错误,说“看起来你的函数没有返回‘唉,你没有资格获得信用卡。资本主义就是这样残酷。’”当收入参数为 75 时。”但是该字符串在控制台中返回(由于某种原因
我正在阅读 Go 的官方教程,但很难理解 Channel 和 Buffered Channels 之间的区别。教程的链接是 https://tour.golang.org/concurrency/2和
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
作为 iOS 新手,有大量书籍可以满足学习基础知识的需求。现在,我想转向一些高级阅读,例如 OAuth 和 SQLite 以及动态 API 派生的 TableView 等。您可以推荐任何资源吗? 最佳
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 8 年前。
前言 很多同学都知道,我们常见的CTF赛事除了解题赛之外,还有一种赛制叫AWD赛制。在这种赛制下,我们战队会拿到一个或多个服务器。服务器的连接方式通常是SSH链接,并且可能一个战队可能会同时有
Memcached是一个自由开源的,高性能,分布式内存键值对缓存系统 Memcached 是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象),这些数据可以是数据库调用、A
Perl 又名实用报表提取语言, 是 Practical Extraction and Report Language 的缩写 Perl 是由 拉里·沃尔(Larry Wall)于19
WSDL 是 Web Services Description Language 的缩写,翻译成中文就是网络服务描述语言 WSDL 是一门基于 XML 的语言,用于描述 Web Services 以
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve thi
我正在寻找解释在 WPF 中创建自定义用户控件的教程。 我想要一个控件,它结合了一个文本 block 、一个文本框和一个启动通用文件打开对话框的按钮。我已经完成了布局,一切都连接好了。它有效,但它是三
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我接近 fourth page of the Django tutorial 的开始看着vote查看,最后是这样的: # Always return an HttpResponseRedirect a
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
是否有任何好的 Qt QSS 教程,或者在某个地方我可以看到样式小部件的示例?如果某处可用,我想要一些完整的引用。除了有关如何设置按钮或某些选项卡样式的小教程外,我找不到任何其他内容。 最佳答案 Qt
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!