引言
web服务无外乎两点,一个是请求,一个是相应。中间经过一系列的处理,我们是为一个sandbox。无论是请求Request,还是响应Response,每个框架都会浓墨重彩地进行深度设计。
本文我们来说一下laravel的请求对象。
代码时间
一个网络请求在到达应用程序之前,经历了http的路由匹配,握手连接, 数据发送等等或简单,或复杂的步骤。也同样有多重请求方式,如GET POST PUT OPTION DELETE 等等标准协议里的内容。
laravel提供了一个助手函数 request(),暴露了一个上下文的 Request 对象可全局操作。我们本文重点说说 用于的请求数据。
比如有一条路由,我们这样便捷地定义:
代码语言:javascript复制Route::post('form', function (IlluminateHttpRequest $request) {
// $request->input()});
在匿名函数中,使用强制类型Request进行注入,变量$request就是一个实例化后的Request对象, 可以访问其属性和方法。
为了演示表单数据的提交,我们构建一个表单:
代码语言:javascript复制<form method="post" action="/post-route?utm=12345">
{{ csrf_field() }}
<input type="text" name="firstName">
<input type="submit"></form>
在此之前先定义路由,初步把请求体的数据全部打印出来:
代码语言:javascript复制Route::post('/post-route', function (Request $request) {
var_dump($request->all());});
调用请求Request的all方法,返回所有字段的值,并格式化为数组,输出内容类似于
代码语言:javascript复制[
'_token' => 'CSRF token here',
'firstName' => 'value',
'utm' => 12345]
其中要注意的是,为了显示区别,utm参数是querystring内传送的, 而firstName字段,是表单内通过POST方法传送的。两者的请求方法不一样。
那么对于用于csrf拦截的字段_token,系统生成,系统自检,我们在表单中并不使用, 可以使用 except 方法将其排除在外。路由内这样做:
代码语言:javascript复制Route::post('/post-route', function (Request $request) {
var_dump($request->except('_token'));});
那么返回数组中,就不会展示 _token 字段了。这类似与黑名单的功能。相对应地使用白名单,手动指定哪些字段需要展示。需要调用 only 方法:
代码语言:javascript复制Route::post('/post-route', function (Request $request) {
var_dump($request->only(['firstName', 'utm']));});
对于单个字段,如何判断是否存在呢?有两个方法,一个是 has(),一个是 exists()。这两者是有细微区别的,has方法要求键名存在,且数值不为空;exists方法仅要求键名存在。
代码语言:javascript复制if ($request->has('invalid_key')) {}
比如上方的代码键名不存在,所以返回 false。如果表单字段 firstName 不填任何值,也即是空字符串。
代码语言:javascript复制$request->has('firstName'); // false$request->exists('firstName'); // true
所以对于大多数的场景,我们其实是在判断是否存在键名,对值并未判断,所以exists 方法更为合适。
上述的all方法返回所有字段的值,如果用于单一字段值的获取,要使用 input()方法:
代码语言:javascript复制Route::post('/post-route', function (Request $request) {
$userName = $request->input('name', 'anonymous');});
第二个参数是指定如果键名不存在时的默认值。
有了input方法,我们来看更复杂的表单提交数组数据的处理办法。首先构造一个表单,并提交数组数据:
代码语言:javascript复制<form method="post" action="/post-route">
{{ csrf_field() }}
<input type="text" name="employees[0][firstName]">
<input type="text" name="employees[0][lastName]">
<input type="text" name="employees[1][firstName]">
<input type="text" name="employees[1][lastName]">
<input type="submit"></form>
这样的表单真是shit对不对,可是框架需要满足这样的需求。处理起来也没问题。PHP就是最为擅长处理数组,所以轻快。laravel对请求体进行数组操作, 还有更高阶的用法,下面是示例:
代码语言:javascript复制Route::post('/post-route', function (Request $request) {
$employeeZeroFirstName = $request->input('employees.0.firstName');
$allLastNames = $request->input('employees.*.lastName');
$employeeOne = $request->input('employees.1');});
我们可以使用明确的键名进行访问,也可以使用通配符进行匹配。上面的方法返回值如下, 大家看看不同的写法,输出会有不同。
假设4个输入框传入的值分别是 "Jim" "Smith" "Bob" "Jones",那么打印如下:
代码语言:javascript复制$employeeZeroFirstName = 'Jim';$allLastNames = ['Smith', 'Jones'];$employeeOne = ['firstName' => 'Bob', 'lastName' => 'Jones'];
laravel按照数组的层级,完整地返回了。整个数组结构大致如下:
代码语言:javascript复制[
'employees' => [
0 => [
'firstName' => 'Jim',
'lastName' => 'Smith',
],
1 => [
'firstName' => 'Bob',
'lastName' => 'Jones',
],
]]
只不过在访问的时候,使用点的方法;也可以使用通配符进行键名匹配。非常灵活。
写在最后
本文通过示例演示了laravel Request请求常用的方法获取表单数据,最重要也用的最少的数组数据的解析, 可以加深大家对于表单数据处理的逻辑。
Happy coding :-)