通过表单提交数据,并使用Session暂存数据实现提示和csrf_field
Request::getPathInfo()实现焦点样式
<a href="{{ url('student/index') }}" class="list-group-item
{{ Request::getPathInfo() == '/student/index' ? 'active': '' }}
" data-request="{{Request::getPathInfo()}}">
学生列表
</a>
<a href="{{ url('student/create') }}" class="list-group-item
{{ Request::getPathInfo() == '/student/create' ? 'active' : '' }}
">
新增学生
</a>
运行以上代码,我们可以看到最终结果:
Request::getPathInfo() 获取路由名称 用于对比路由是否需要加上active样式,注意得到的结果前面有个斜线“/”,所以对比路由的时候也要加上斜线!
url是通过路由名称生成访问地址,具体请见《Blade模板中的URL获取》
在模板中使用Request和Session,直接使用即可。
提交数据的两种方式
使用指定的路由地址提交
HTML(在面向对象中,都以模型的名字作为数组的key)案例中的模型名字是app/Student.php,所以使用模型名字Student:
<form class="form-horizontal" method="post" action="{{ url('student/save') }}">
<input type="text" id="name" name="Student[name]" placeholder="请输入学生姓名">
<input type="text" id="age" name="Student[age]" placeholder="请输入学生年龄">
<input type="radio" name="Student[sex]" value="10">未知
<input type="radio" name="Student[sex]" value="20">男
<input type="radio" name="Student[sex]" value="30">女
</form>
新建一个路由:
Route::any('student/save', [
'uses' => 'StudentController@save'
]);
在控制器中新建save方法,并书写代码:
public function save(Request $request)
{
// 获取所有以Student为下标的数组数据
// <input name="Student[name]" name="Student[age]"
// 最终得到array(3) { ["name"]=> string(3) "asd" ["age"]=> string(3) "sad" ["sex"]=> string(2) "20" }
$data = $request->input('Student');
// 实例化一个模型 并且设置值执行save方法进行保存到数据库
$student = new Student();
$student->name = $data['name'];
$student->age = $data['age'];
$student->sex = $data['sex'];
// 如果成功
if ($student->save()) {
// 跳转到指定页面
return redirect('student/index');
} else {
// 失败返回上一个请求页面
return redirect()->back();
}
}
注意这个Request 是 Illuminate\Http\Request获取一个$request实例,所以要在脚本开始位置使用:
// 使用请求参数的save方法中request需要使用Illuminate\Http\Request
use Illuminate\Http\Request;
使用当前页面进行提交
比如2.1中的HTML,是通过student/create方法进行渲染的:
public function create(Request $request)
{
// 之后逻辑代码写在此处
return view('student.create');
}
<form class="form-horizontal" method="post" action="">...</form>
action=""不填写,默认会提交到student/create这个路由对应的方法中,路由:
Route::any('student/create', [
'uses' => 'StudentController@create'
]);
再在控制器中书写逻辑(正常都是get请求,只有提交是post请求,所以只要判断请求的类型即可):
if ($request->isMethod('post')) {
$data = $request->input('Student');
// 使用模型的::create方法会批量赋值,修改Student中的$fillable属性
if (Student::create($data)) {
// 比如成功或者失败提示,用到session的暂存数据,所以要加入到中间件中
// with(key, 信息) 暂存数据只在第一次请求的时候生效
return redirect('student/index')->with('success', '添加成功');
} else {
// 失败返回上一个请求页面
return redirect()->back();
}
}
return view('student.create');
$request->isMethod('post') 可以判断请求的类型。
在模板中读取Session
详情请参见我的另一篇文章:《控制器之Session》
注web中间件从laravel 5.2.27版本以后默认全局加载,不需要自己手动载入,如果自己手动重复载入,会导致session无法加载的情况!!参考链接
所以不要将路由写在中间件之中,会导致session不可用!如下写法是错误的!
// 是错误的!这样写会导致session不可用,直接在routes.php中书写即可!
Route::group(['middleware' => ['web']], function () {
Route::get('student/index', [
'uses' => 'StudentController@index'
]);
Route::any('student/create', [
'uses' => 'StudentController@create'
]);
Route::any('student/save', [
'uses' => 'StudentController@save'
]);
});
当使用->with()传递暂存值之后,在模板中:
<!-- 成功提示框 -->
{{--如果session中有success这个值就让他显示,
使用has判断 5.2以后web中间件都是自动加载的 不需要在手动引用了,否则会导致session不可用--}}
@if(Session::has('success'))
<div class="alert alert-success alert-dismissible">
<!-- 操作成功提示 -->
{{ Session::get('success') }}
</div>
@endif
<!-- 失败提示框 -->
@if(Session::has('error'))
<div class="alert alert-danger alert-dismissible">
<!-- 操作失败提示 -->
{{ Session::get('error') }}
</div>
@endif
csrf_field()防止XSS攻击CSRF
Laravel框架中有此要求:任何指向 web 中 POST, PUT 或 DELETE 路由的 HTML 表单请求都应该包含一个 CSRF 令牌(CSRF token),否则,这个请求将会被拒绝。可以参考链接:https://blog.csdn.net/cnwyt/article/details/79540396
如果出现报错:报错TokenMismatchException in VerifyCsrfToken.php line 67 如下:
那么,解决这个错误的方法就是在表单中插入一个{{ csrf_field() }},如下:
<form class="form-horizontal" method="post" action="">
{{ csrf_field() }}
<div class="form-group">...</div>
...
</form>
csrf_field() 会生成一个隐藏的input表单,里面带一个token字段防止xss攻击(即是csrf)。不加的话提交表单会报错,这里十分重要,请谨记。