[Laravel] 07 - Project: functions in Controller
故事背景
一、项目预览
From: https://www.imooc.com/video/12521
表单操作
一、新增信息
既然是操作,自然会想到:控制器。
- 控制器
[1] 路由 ----> 函数 create( )
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']);
Route::any('student/update/{id}', ['uses' => 'StudentController@update']);
Route::any('student/detail/{id}', ['uses' => 'StudentController@detail']);
Route::any('student/delete/{id}', ['uses' => 'StudentController@delete']);
});
[app/Http/StudentController.php]
// 添加页面
public function create(Request $request)
{
$student = new Student(); if ($request->isMethod('POST')) {
-----------------------------------------------------------------------
// 1. 控制器验证
// 2. Validator类验证
------------------------------------------------------------------------ $data = $request->input('Student'); if (Student::create($data) ) {
return redirect('student/index')->with('success', '添加成功!');
} else {
return redirect()->back();
}
} return view('student.create', [
'student' => $student
]);
}
[2] 函数 create( ) return --> 视图
- 表单提交
以上只是打开create页面,这里才是submit。
// 保存添加
public function save(Request $request)
{
$data = $request->input('Student'); $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(); // 返回上一个请求页面
} }
[1] Submit 表单内容提交的过程是怎样的?
Goto: [PHP] 03 - Form & Input
[2] 也可以默认将逻辑写在save中,也即是action中采用默认形式(设置为空字符串)
- 提交结果
[1] 表单空内容提交,可采用“中间件”方法解决,便不会直接报系统错误。
[2] tokenMIsMatchException错误的解决方案:
<form class="form-horizontal" method="post" action=""> {{ csrf_field() }} 该字段:生成了隐藏的input表单,自带token字段 <div class="form-group">
<label for="name" class="col-sm-2 control-label">姓名</label> <div class="col-sm-5">
<input type="text" name="Student[name]"
value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"
class="form-control" id="name" placeholder="请输入学生姓名">
</div>
<div class="col-sm-5">
<p class="form-control-static text-danger">{{ $errors->first('Student.name') }}</p>
</div>
</div>
<div class="form-group">
<label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-5">
<input type="text" name="Student[age]"
value="{{ old('Student')['age'] ? old('Student')['age'] : $student->age }}"
class="form-control" id="age" placeholder="请输入学生年龄">
</div>
<div class="col-sm-5">
<p class="form-control-static text-danger">{{ $errors->first('Student.age') }}</p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">性别</label> <div class="col-sm-5">
@foreach($student->sex() as $ind=>$val)
<label class="radio-inline">
<input type="radio" name="Student[sex]"
{{ isset($student->sex) && $student->sex == $ind ? 'checked' : '' }}
value="{{ $ind }}"> {{ $val }}
</label>
@endforeach
</div>
<div class="col-sm-5">
<p class="form-control-static text-danger">{{ $errors->first('Student.sex') }}</p>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">提交</button>
</div>
</div>
</form>
[3] 判断Session中的参数来控制UI片段的显示。
<!-- 成功提示框 -->
@if (Session::has('success'))
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>成功!</strong> {{ Session::get('success') }}
</div>
@endif <!-- 失败提示框 -->
@if (Session::has('error'))
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>失败!</strong> {{ Session::get('error') }}
</div>
@endif
二、数据验证
- 出错提示视图
[1] 获取$error变量后,循环打印出。
@if (count($errors)) <div class="alert alert-danger">
<ul>
<li>{{ $errors->first() }}</li>
</ul>
</div> <div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div> @endif
[2] 视图效果如下。
[3] 那么,$error 从哪里来?
通过中间件将出错信息绑定到所有的视图中,视图中可直接获取。
- 控制器验证法
Ref: https://www.imooc.com/video/12522
// 1. 控制器验证
$this->validate($request, [
'Student.name' => 'required|min:2|max:20',
'Student.age' => 'required|integer',
'Student.sex' => 'required|integer',
], [
'required' => ':attribute 为必填项',
'min' => ':attribute 长度不符合要求',
'integer' => ':attribute 必须为整数',
], [
'Student.name' => '姓名',
'Student.age' => '年龄',
'Student.sex' => '性别',
]);
[1] $this:当前控制器;validate验证方法;
[2] 如下提示不够友好,需要替换下内容;
[3] 中间件的效果
如果没有验证通过,中间件ShareErrorsFromSession开始发挥作用:
(1) 框架会抛出一个异常;
(2) 异常被自动捕获,重定向到上一个页面;
(3) 错误信息被存在session中,且绑定到视图上;
所以,返回的“上一个页面"就可以直接在视图中获得出错信息 by $error变量。
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
], 'api' => [
'throttle:60,1',
],
];
- Validator类验证法
\Validator全局的。
// 2. Validator类验证
$validator = \Validator::make($request->input(), [
'Student.name' => 'required|min:2|max:20',
'Student.age' => 'required|integer',
'Student.sex' => 'required|integer',
], [
'required' => ':attribute 为必填项',
'min' => ':attribute 长度不符合要求',
'integer' => ':attribute 必须为整数',
], [
'Student.name' => '姓名',
'Student.age' => '年龄',
'Student.sex' => '性别',
]); if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}
- 数据保持
[1] 点击提交后,如果执行失败,注册的信息保留住,方便查看到底错在了哪里。
在返回上一个页面的同时并填充原始的信息($request)。
if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}
[2] 对应地,使用如下old方法来提取withInput()中保存的数据。
<div class="form-group">
<label for="name" class="col-sm-2 control-label">姓名</label> <div class="col-sm-5">
<input type="text" name="Student[name]"
value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"
class="form-control" id="name" placeholder="请输入学生姓名">
</div>
<div class="col-sm-5">
<p class="form-control-static text-danger">{{ $errors->first('Student.name') }}</p>
</div>
</div>
三、通过模型处理性别
- 模型中的性别属性
问题,导致数据库中存储数据的形式是数字。其实这也并非是"大问题”。
Self 与 This
在访问PHP类中的成员变量或方法时,如果被引用的变量或者方法被声明成const(定义常量)或者static(声明静态),那么就必须使用操作符::,
反之如果被引用的变量或者方法没有被声明成const或者static,那么就必须使用操作符->。
一句话,self是引用静态类的类名,而$this是引用非静态类的实例名。
- Model中增加属性
性别属性其实是枚举类属性的一个典型例子,在此作为典型案例进行分析。
希望:只修改这里,相应的部分都能自动改变。
public function sex($ind = null)
{
$arr = [
self::SEX_UN => '未知',
self::SEX_BOY => '男',
self::SEX_GRIL => '女',
]; if ($ind !== null) {
return array_key_exists($ind, $arr) ? $arr[$ind] : $arr[self::SEX_UN];
} return $arr;
}
- ’学生列表‘View中获取属性
学生列表中做出调整。
<tbody>
@foreach($students as $student)
<tr>
<th scope="row">{{ $student->id }}</th>
<td>{{ $student->name }}</td>
<td>{{ $student->age }}</td>
<td>{{ $student->sex($student->sex) }}</td> # 这里提取到的就是字符串了
<td>{{ date('Y-m-d', $student->created_at) }}</td>
<td>
<a href="{{ url('student/detail', ['id' => $student->id]) }}">详情</a>
<a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
<a href="{{ url('student/delete', ['id' => $student->id]) }}"
onclick="if (confirm('确定要删除吗?') == false) return false;">删除</a>
</td>
</tr>
@endforeach
</tbody>
- '创建'View中获取属性
Create界面原始写法,就是一组 radio button。
取出student中的key和value:as $ind => $val
四、修改表单
Ref: https://www.imooc.com/video/12524
我们的思路是:尽量利用“添加表单”的逻辑和页面。
- 添加链接
<tbody>
@foreach($students as $student)
<tr>
<th scope="row">{{ $student->id }}</th>
<td>{{ $student->name }}</td>
<td>{{ $student->age }}</td>
<td>{{ $student->sex($student->sex) }}</td>
<td>{{ date('Y-m-d', $student->created_at) }}</td>
<td>
<a href="{{ url('student/detail', ['id' => $student->id]) }}">详情</a>
<a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
<a href="{{ url('student/delete', ['id' => $student->id]) }}"
onclick="if (confirm('确定要删除吗?') == false) return false;">删除</a>
</td>
</tr>
@endforeach
</tbody>
- 修改页面
[1] 控制器 ----> “页面”,获得了模型的数据:$student
public function update(Request $request, $id)
{
# 先获得表单
$student = Student::find($id); if ($request->isMethod('POST')) { // 来自client的POST,携带了“edit”信息 $this->validate($request, [
'Student.name' => 'required|min:2|max:20',
'Student.age' => 'required|integer',
'Student.sex' => 'required|integer',
], [
'required' => ':attribute 为必填项',
'min' => ':attribute 长度不符合要求',
'integer' => ':attribute 必须为整数',
], [
'Student.name' => '姓名',
'Student.age' => '年龄',
'Student.sex' => '性别',
]);
# 这里获得了数据,有待”视图“去使用$student
$data = $request->input('Student');
$student->name = $data['name'];
$student->age = $data['age'];
$student->sex = $data['sex']; if ($student->save()) {
return redirect('student/index')->with('success', '修改成功-' . $id);
}
} return view('student.update', [
'student' => $student
]);
}
Ref:laravel的$request->input()和$request->get()有什么区别?
Ref:Laravel 5 $request->input vs Input::get
走的流程不同
input获取数据的流程是把post过来的数据与URL里的Query合并,然后用helper里的data_get方法去取数据
/* implement */
[2] “页面”部分
old代表"最新的数据“,如果是edit,也就没有”最新数据“这么一说,old里就为空。那么就从模型student中取数据。
value="{{ old('Student')['name'] ? old('Student')['name'] : $student->name }}"
以上代码依次在age,gender等其他属性处做相应的调整。
[gender] <div class="col-sm-5">
@foreach($student->sex() as $ind=>$val)
<label class="radio-inline">
<input type="radio" name="Student[sex]"
{{ isset($student->sex) && $student->sex == $ind ? 'checked' : '' }} // 遍历了各个枚举,然后选中额加个checked。
value="{{ $ind }}"> {{ $val }}
</label>
@endforeach
</div>
五、详情查看
- 控制器
public function detail($id)
{
$student = Student::find($id); return view('student.detail', [
'student' => $student
]);
}
- 控制器 ----> 视图
@extends('common.layouts') @section('content') <div class="panel panel-default">
<div class="panel-heading">学生详情</div> <table class="table table-bordered table-striped table-hover ">
<tbody>
<tr>
<td width="50%">ID</td>
<td>{{ $student->id }}</td>
</tr>
<tr>
<td>姓名</td>
<td>{{ $student->name }}</td>
</tr>
<tr>
<td>年龄</td>
<td>{{ $student->age }}</td>
</tr>
<tr>
<td>性别</td>
<td>{{ $student->sex($student->sex) }}</td>
</tr>
<tr>
<td>添加日期</td>
<td>{{ date('Y-m-d', $student->created_at) }}</td>
</tr>
<tr>
<td>最后修改</td>
<td>{{ date('Y-m-d', $student->updated_at) }}</td>
</tr>
</tbody>
</table>
</div>
@stop
六、删除信息
- 删除模型中的数据
public function delete($id)
{ $student = Student::find($id); if ($student->delete()) {
return redirect('student/index')->with('success', '删除成功-' . $id);
} else {
return redirect('student/index')->with('error', '删除失败-' . $id);
}
}
- 删除确认框
删除不需要专门的删除页面,利用onClick方法即可。
<tbody>
@foreach($students as $student)
<tr>
<th scope="row">{{ $student->id }}</th>
<td>{{ $student->name }}</td>
<td>{{ $student->age }}</td>
<td>{{ $student->sex($student->sex) }}</td>
<td>{{ date('Y-m-d', $student->created_at) }}</td>
<td>
<a href="{{ url('student/detail', ['id' => $student->id]) }}">详情</a>
<a href="{{ url('student/update', ['id' => $student->id]) }}">修改</a>
<a href="{{ url('student/delete', ['id' => $student->id]) }}" onclick="if (confirm('确定要删除吗?') == false) return false;">删除</a>
</td>
</tr>
@endforeach
</tbody>
本项目剖析到此结束。
[Laravel] 07 - Project: functions in Controller的更多相关文章
- Project 03- STM32F4xx PID controller
Project 03- STM32F4xx PID controller CMSIS files from ARM provides ARM Math functions. There are als ...
- Ubuntu开机时提示“piix4_smbus 0000:00:07.3: SMBus Host controller not enabled”
问题描述:Ubuntu开机时提示“piix4_smbus 0000:00:07.3: SMBus Host controller not enabled” 版本:Ubuntu 18.04 VMw ...
- [Laravel] 06 - Project: from Usercase to View
故事背景 一.项目预览 From: https://www.imooc.com/video/12518 二.知识点 通过项目复习之前的重难点,在此列出并解决. /* implement */ 项目开始 ...
- [Python] 07 - Statements --> Functions
故事背景 一.阶级关系 1. Programs are composed of modules.2. Modules contain statements.3. Statements contain ...
- Eloquent JavaScript #07# Project: A Robot
索引 Notes Excercise Measuring a robot Robot efficiency Persistent group 注释即笔记: const roads = [ " ...
- Laravel 5.* 中路由绑定 Controller 包含子目录写法
https://blog.csdn.net/maxsky/article/details/54017981 [可以使用命令在项目根目录一键创建 php artisan make:controller ...
- [Laravel] 14 - REST API: Laravel from scratch
前言 一.基础 Ref: Build a REST API with Laravel API resources Goto: [Node.js] 08 - Web Server and REST AP ...
- [Code::Blocks] Install wxWidgets & openCV
The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...
- 本人SW知识体系导航 - Programming menu
将感悟心得记于此,重启程序员模式. js, py, c++, java, php 融汇之全栈系列 [Full-stack] 快速上手开发 - React [Full-stack] 状态管理技巧 - R ...
随机推荐
- PHP内置的预定义常量大全
URL:http://www.php.net/manual/en/reserved.constants.php 预定义常量:核心预定义常量,标准预定义常量----------------------- ...
- 【.NET线程--进阶(一)】--线程方法详解
上篇博客从线程的基本概况开始着重讨论了线程,进程,程序之间的区别,然后讨论了线程操作的几个类,并通过实例来说明了线程的创建方法.本篇博客将会带大家更深入的了解线程,介绍线程的基本方法,并通过一个Dem ...
- Android 实战之酷云(一)
前言 大家好啊!好久没有见到我了吧.为什么呢!当然是由于开学啦,这学期非常多课,身为部长实验室也也非常多活动和一堆小师弟.同一时候还有蓝桥杯和华为软件开发大赛.并且近期在做一个综合性比較高的作品,没错 ...
- 微软BI 之SSRS 系列 - 如何让报表在一页显示,两种常用的技巧
通常情况下,SSRS 报表在页面内容过多的时候会自动分页.但有的时候当页面内容不是很多,大概最多2页的情况下,或者客户要求所有内容必须在一页显示时,应该如何设置. 实际上,要考虑两种情况:第一种情况是 ...
- 基于SIFT特征的全景图像拼接
基于SIFT特征的全景图像拼接 分类: image Machine learning2013-07-05 13:33 2554人阅读 评论(3) 收藏 举报 基于SIFT特征的全景图像拼接 分类: 计 ...
- 使用IDEA导出可运行的jar包,包含引用第三方jar包
这里我使用的第三方jar包是数据库的JDBC jar包导出案例. 1.创建一个Module,名称为dataBase,在里面我们先创建一个folder用来包含所需要的jar包,命名为lib 2.从外界复 ...
- Background Media Recovery terminated with ORA-1274 after adding a Datafile (Doc ID 739618.1)
APPLIES TO: Oracle Database - Enterprise Edition - Version 9.2.0.1 to 12.1.0.2 [Release 9.2 to 12.1] ...
- java多线程状态
造成线程进入阻塞状态的情况大致可分为: 1.调用sleep()方法 2.调用阻塞式IO方法 3. 4.等待通知 5.调用suspend(),程序挂起.
- 转发-基于ASP.NET MVC 4/5 Razor的模块化/插件式架构实现
基于ASP.NET MVC 4/5 Razor的模块化/插件式架构实现 概述 在日常开发中, 我们经常谈起模块化/插件化架构,这样可既可以提高开效率,又可以实现良好的扩展性,尤其对于产品化的系统有 ...
- Socket网络编程--简单Web服务器(4)
上一小节已经实现了对图片的传输,接下来就是判断文件是否为js,css,png等格式.我们增加一个函数用于判断格式 int WebServer::get_filetype(char *type,char ...