新增关联查询、增加字段模糊查询
一、新增关联查询表
主表:fa_student(学生表)
关联表:
fa_stuclass(班级表)
fa_stuscore(成绩表)
fa_studentmoney(学费表)
一键CRUD
二、一键生成菜单,显示结果
尝试通过关联表中的信息进行模糊查询,会发现无法查询到
三、在控制器中设置查询功能
位置:application/admin/controller/pim/Test3.php
$this->searchFields = "stuclass.class,studentmoney.money,stuscore.score";//增加三个别表的查询功能,若未进行设置,默认只能快速查询id的值
其中三个字段的信息stuclass.class,studentmoney.money,stuscore.score可在浏览器中的开发现者工具中查看流程如下:
①在页面中右击鼠标,点击“检查”
②选择“网络/Network”
③刷新页面数据,点击页面数据
④查看对应数据字段即可
四、模糊查询功能实现测试
新增界面修改
一、修改界面样式
位置:application/admin/view/pim/test3/add.html
暂时先给班级id一个默认值,增加学费,分数的文本框
新增的分数,学费文本框:
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuscore.score')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-score" class="form-control" name="row[score]" type="number">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Studentmoney.money')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-money" class="form-control" name="row[money]" type="number">
</div>
</div>
修改班级id下拉列表为文本框,给定默认值:
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuclass_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-stuclass_id" data-rule="required" data-source="stuclass/index" class="form-control" name="row[stuclass_id]" type="text" value="1">
</div>
</div>
add.html的全部代码
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""> <div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" class="form-control" name="row[name]" type="text">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Age')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-age" class="form-control" name="row[age]" type="number">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuscore.score')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-score" class="form-control" name="row[score]" type="number">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Studentmoney.money')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-money" class="form-control" name="row[money]" type="number">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuclass_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-stuclass_id" data-rule="required" data-source="stuclass/index" class="form-control" name="row[stuclass_id]" type="text" value="1">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
二、关联表存入数据
此时添加的数据只会存入主表中,但分数,成绩并不会一并存入,需在控制器手动添加存入信息
①在基类控制器引入的traits方法中,寻找并复制增删改的代码以及所需头部文件
位置:application/admin/library/traits/Backend.php
增删改代码
/**
* 添加
*
* @return string
* @throws \think\Exception
*/
public function add()
{
if (false === $this->request->isPost()) {
return $this->view->fetch();
}
$params = $this->request->post('row/a');
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
$params = $this->preExcludeFields($params); if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
$params[$this->dataLimitField] = $this->auth->id;
}
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
$this->model->validateFailException()->validate($validate);
}
$result = $this->model->allowField(true)->save($params);
Db::commit();
} catch (ValidateException|PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($result === false) {
$this->error(__('No rows were inserted'));
}
$this->success();
} /**
* 编辑
*
* @param $ids
* @return string
* @throws DbException
* @throws \think\Exception
*/
public function edit($ids = null)
{
$row = $this->model->get($ids);
if (!$row) {
$this->error(__('No Results were found'));
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
$this->error(__('You have no permission'));
}
if (false === $this->request->isPost()) {
$this->view->assign('row', $row);
return $this->view->fetch();
}
$params = $this->request->post('row/a');
if (empty($params)) {
$this->error(__('Parameter %s can not be empty', ''));
}
$params = $this->preExcludeFields($params);
$result = false;
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
$row->validateFailException()->validate($validate);
}
$result = $row->allowField(true)->save($params);
Db::commit();
} catch (ValidateException|PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if (false === $result) {
$this->error(__('No rows were updated'));
}
$this->success();
} /**
* 删除
*
* @param $ids
* @return void
* @throws DbException
* @throws DataNotFoundException
* @throws ModelNotFoundException
*/
public function del($ids = null)
{
if (false === $this->request->isPost()) {
$this->error(__("Invalid parameters"));
}
$ids = $ids ?: $this->request->post("ids");
if (empty($ids)) {
$this->error(__('Parameter %s can not be empty', 'ids'));
}
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
$list = $this->model->where($pk, 'in', $ids)->select(); $count = 0;
Db::startTrans();
try {
foreach ($list as $item) {
$count += $item->delete();
}
Db::commit();
} catch (PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($count) {
$this->success();
}
$this->error(__('No rows were deleted'));
}
头部文件
use Exception;
use think\Db;
use think\exception\PDOException;
use think\exception\ValidateException;
②将以上代码一并复制到当前控制器
位置:application/admin/controller/pim/Test3.php
(一)对新增页面进行修改
对复制过来的代码进行设置,增加数据添加至关联表中
新增关联数据到关联表:☆☆☆☆☆
$this->model->stuscore()->save(['score'=>$params['score'],'student_id'=>$this->model->id]);
$this->model->studentmoney()->save(['money'=>$params['money'],'student_id'=>$this->model->id]);
新增方法的全部代码剖析
/**
* 添加
*
* @return string
* @throws \think\Exception
*/
public function add()
{
//判断是否为Post请求,===先比较类型再比较值,如果类型不同直接返回false无需再进行值的比较
if (false === $this->request->isPost()) {
//用于渲染模板文件输出
return $this->view->fetch();
}
//前端页面所有提交的表单数据都是以row命名的数组。post("row/a")的意思是,获取post提交的以row命名的数据,/a的作用是强制转为数组。
//例如前端数据:name="row[money]"
$params = $this->request->post('row/a');
//如果前端提交的数据为空
if (empty($params)) {
//提示参数xx不能为空
$this->error(__('Parameter %s can not be empty', ''));
}
//
$params = $this->preExcludeFields($params);//前台提交过来,需要排除的字段数据,根据引用基类控制器中的方法(引用的traits中的)
//引用基类控制器中的:是否开启数据限制dataLimit,数据限制开启时自动填充限制字段值dataLimitFieldAutoFill属性
//如果dataLimit为true,并且dataLimitFieldAutoFill为true,表明开启了数据的权限设置
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
//调用基类控制器的属性dataLimitField,值为admin_id;
//调用基类控制器中的auth属性,$this->auth->id表示获取管理员ID,$this->auth->字段名表示获取管理员的其它信息
$params[$this->dataLimitField] = $this->auth->id;
}
//给变量result赋值为false
$result = false;
//事务模板:目的为了解决服务器中断等服务器造成的问题导致数据库无法正常操作问题
// Db::startTrans();
// try {
//开始数据库操作
// .
// ..
// ...
// Db::commit();
// }
// catch (Exception $ex)
// {
//Db::rollback();
//throw $ex;
// }
Db::startTrans();
try {
//插入异动记录
//是否采用模型验证
if ($this->modelValidate) {
//str_replace()函数替换字符串中的一些字符(区分大小写)
//get_class() 返回对象的类名
//表示将get_class($this->model)中的\\model\\转换为为\\validate\\
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
//$this->modelValidate:调用基类控制器中的 是否开启Validate验证modelValidate属性,获取其值(基类控制器中默认是false)
//$this->modelSceneValidate:调用基类控制器中的 是否开启模型场景验证modelSceneValidate属性,获取其值(基类控制器中默认是false)
//判断$this->modelValidate其值是否为布尔类型(true/false)
//$name . '.add':表示一个变量name连接一个字符串.add,第一个.表示拼接
//($this->modelSceneValidate ? $name . '.add' : $name):判断$this->modelSceneValidate的值,为真就执行$name . '.add',否则执行$name
//完整解释:变量$validate的值为:
//判断$this->modelValidate的值是否为布尔类型,
//是布尔类型:
//判断$this->modelSceneValidate的值是否为真
//为真
//$validate变量值就为$name . '.add'(变量name拼接字符串.add)
//为假
//$validate变量值就为$name
//不是布尔类型
//$validate变量值就为$this->modelValidate的值
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
//validateFailException()验证失败抛出异常,validate($validate)对$validate进行验证
$this->model->validateFailException()->validate($validate);
}
//allowField(true)过滤掉非数据库字段,将数据$params存入当前模型对应的数据库
$result = $this->model->allowField(true)->save($params);
//将前端的分数,学费分别存入分数表与学费表中(由于是学生的班级信息是从班级表得到的,则无需将班级再插入班级表)(hasone才需要插入)
//$this->model->id:这个模型对应数据库的id
//$this->model->stuscore()表示的就是fa_stuscore数据库, $this->model->studentmoney()表示的就是fa_studentmoney数据库
$this->model->stuscore()->save(['score'=>$params['score'],'student_id'=>$this->model->id]);
$this->model->studentmoney()->save(['money'=>$params['money'],'student_id'=>$this->model->id]);
//提交上一个数据库事务(提交事务)
Db::commit();
//判断捕获到的异常类型
} catch (ValidateException|PDOException|Exception $e) {
// 回滚事务(如果事务中的某个点发生故障,对所有表的删、改、写操作(则所有更新)都可以回滚到事务开始之前的状态回滚事务 )
Db::rollback();
//提示错误信息
//$e->getMessage():获取错误信息,并通过echo输出此错误信息。
$this->error($e->getMessage());
}
//对$result于false进行先类型后值的比较,判断是否是bool类型中的false(先判断是否是布尔,再判断值是否一致)
if ($result === false) {
//提示错误信息,内容是多语言中的'No rows were inserted'的值
$this->error(__('No rows were inserted'));
}
//执行成功
$this->success();
}
修改页面
一、修改界面样式
位置:application/admin/view/pim/test3/edit.html
增加学费,分数的文本框,去掉班级id的下拉选择
新增的分数,学费文本框:
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuscore.score')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-score" class="form-control" name="row[score]" type="number" value="{$row.stuscore.score|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Studentmoney.money')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-money" class="form-control" name="row[money]" type="number" value="{$row.studentmoney.money|htmlentities}">
</div>
</div>
修改班级id下拉列表为文本框:
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuclass_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-stuclass_id" data-rule="required" data-source="stuclass/index" class="form-control" name="row[stuclass_id]" type="text" value="{$row.stuclass_id|htmlentities}">
</div>
</div>
exit.html的全部代码
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action=""> <div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Age')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-age" class="form-control" name="row[age]" type="number" value="{$row.age|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuscore.score')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-score" class="form-control" name="row[score]" type="number" value="{$row.stuscore.score|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Studentmoney.money')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-money" class="form-control" name="row[money]" type="number" value="{$row.studentmoney.money|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Stuclass_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-stuclass_id" data-rule="required" data-source="stuclass/index" class="form-control" name="row[stuclass_id]" type="text" value="{$row.stuclass_id|htmlentities}">
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
复制部分以有新增操作一并完成
(二)对编辑页面进行修改
对复制过来的代码进行设置,增加关联表修改数据的存储
修改关联数据到关联表:☆☆☆☆☆
//对数据库数据进行修改
//表示对row中的stuscore中的score设置值为$params['score']
//表示对row中的studentmoney中的money设置值为$params['money']
$row->stuscore->score=$params['score'];
$row->studentmoney->money=$params['money'];
//对数据库表fa_stuscore,与数据库表studentmoney进行保存
$row->together(['stuscore','studentmoney'])->save();
编辑方法的全部代码剖析
/**
* 编辑
*
* @param $ids
* @return string
* @throws DbException
* @throws \think\Exception
*/
public function edit($ids = null)
{
//step1从数据库取得该条数据
//get()函数:利用键来获取值
//获取到该模型对应的变量ids对应的值存入变量row中
$row = $this->model->get($ids);
//如果$row不存在
if (!$row) {
//提示多语言中No Results were found对应的错误信息
$this->error(__('No Results were found'));
}
//step2检查是否有数据操作权限
//调用基类控制器中的方法:getDataLimitAdminIds(),来获取数据限制的管理员ID,存入变量adminIds中
$adminIds = $this->getDataLimitAdminIds();
//$this->dataLimitField:调用基类控制器中的dataLimitField属性:数据限制字段,来获取字段名
//$row[$this->dataLimitField]:获取到$row中键名为$this->dataLimitField对应的值
//in_array(要在数组搜索的值,搜索的数组)
//判断当前用户$row[$this->dataLimitField]是不是在数组$adminIds中
if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
//如果行数据不存在,返回You have no permission在语言库中对应的信息
$this->error(__('You have no permission'));
}
//step3更新数据库
//使用post传参,表明数据库的修改
//判断两者类型是否相同,再判断值是否一致
if (false === $this->request->isPost()) {
//满足条件
//给view视图层页面变量row赋值为$row
$this->view->assign('row', $row);
//用于渲染模板文件输出
return $this->view->fetch();
}
//获取前端post提交的以row命名的数据,/a的作用是强制转为数组
$params = $this->request->post('row/a');
//如果$params为空
if (empty($params)) {
//提示参数xx不能为空
$this->error(__('Parameter %s can not be empty', ''));
}
//前台提交过来,需要排除的字段数据,根据引用基类控制器中的方法(引用的traits中的)
$params = $this->preExcludeFields($params);
//给变量result赋值为false
$result = false;
//开启事务
Db::startTrans();
try {
//是否采用模型验证
if ($this->modelValidate) {
//str_replace()函数替换字符串中的一些字符(区分大小写)
//get_class() 返回对象的类名
//表示将get_class($this->model)中的\\model\\转换为为\\validate\\
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
//$this->modelValidate:调用基类控制器中的 是否开启Validate验证modelValidate属性,获取其值(基类控制器中默认是false)
//$this->modelSceneValidate:调用基类控制器中的 是否开启模型场景验证modelSceneValidate属性,获取其值(基类控制器中默认是false)
//判断$this->modelValidate其值是否为布尔类型(true/false)
//$name . '.add':表示一个变量name连接一个字符串.add,第一个.表示拼接
//($this->modelSceneValidate ? $name . '.add' : $name):判断$this->modelSceneValidate的值,为真就执行$name . '.add',否则执行$name
//完整解释:变量$validate的值为:
//判断$this->modelValidate的值是否为布尔类型,
//是布尔类型:
//判断$this->modelSceneValidate的值是否为真
//为真
//$validate变量值就为$name . '.add'(变量name拼接字符串.add)
//为假
//$validate变量值就为$name
//不是布尔类型
//$validate变量值就为$this->modelValidate的值
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
//validateFailException()验证失败抛出异常,validate($validate)对$validate进行验证
$row->validateFailException()->validate($valrowidate);
}
//allowField(true)过滤掉非数据库字段,将数据$params存入当前模型对应的数据库
$result = $row->allowField(true)->save($params);
//对数据库数据进行修改
//表示对row中的stuscore中的score设置值为$params['score']
//表示对row中的studentmoney中的money设置值为$params['money']
$row->stuscore->score=$params['score'];
$row->studentmoney->money=$params['money'];
//对数据库表fa_stuscore,与数据库表studentmoney进行保存
$row->together(['stuscore','studentmoney'])->save();
//提交上一个数据库事务(提交事务)
Db::commit();
//判断捕获到的异常类型
} catch (ValidateException|PDOException|Exception $e) {
// 回滚事务(如果事务中的某个点发生故障,对所有表的删、改、写操作(则所有更新)都可以回滚到事务开始之前的状态回滚事务 )
Db::rollback();
//提示错误信息
//$e->getMessage():获取错误信息,并通过echo输出此错误信息。
$this->error($e->getMessage());
}
//对$result于false进行先类型后值的比较,判断是否是bool类型中的false(先判断是否是布尔,再判断值是否一致)
if (false === $result) {
//提示错误信息,内容是多语言中的'No rows were inserted'的值
$this->error(__('No rows were updated'));
}
//执行成功
$this->success();
}
(三)对删除数据进行修改
在控制器对复制过来的del删除功能进行编辑,增加对关联表数据的删除
删除关联表中的数据:☆☆☆☆☆
方法加载循环中
foreach ($list as $item) {
//$count=$count+$item->delect()
$count += $item->delete();
//对关联表进行循环删除语句
//$item->together(['stuscore','studentmoney'])->delete();
// 或者
// $item->stuscore()->delete();
// $item->studentmoney()->delete();
//表示对数据库表fa_stuscore与fa_studentmoney中的数据进行删除
$item->together(['stuscore','studentmoney'])->delete();
}
删除方法的全部代码剖析
/**
* 删除
*
* @param $ids
* @return void
* @throws DbException
* @throws DataNotFoundException
* @throws ModelNotFoundException
*/
public function del($ids = null)
{
//如果没有进行Post请求
if (false === $this->request->isPost()) {
//提示Invalid parameters对应多语言中的文本信息
$this->error(__("Invalid parameters"));
}
//三目运算符省略中间的表达式。例如x?:y等同于x?x:y
//这里就是$ids ?$ids: $this->request->post("ids")
//判断$ids是真的吗,如果是执行$ids = $ids,如果不是执行$ids =$this->request->post("ids")
$ids = $ids ?: $this->request->post("ids");
//如果$ids为空
if (empty($ids)) {
//提示参数xx不能为空的错误信息
$this->error(__('Parameter %s can not be empty', 'ids'));
}
//$this->model->getPk(),获取该模型数据库的主键,赋值给变量pk
$pk = $this->model->getPk();
//$this->getDataLimitAdminIds(),获取数据限制的管理员ID,存入变量adminIds中
$adminIds = $this->getDataLimitAdminIds();
//判断$adminIds是否是数组,如果是
if (is_array($adminIds)) {
//当$this->dataLimitField对应的字段在$adminIds中
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
//当变量pk的值在$ids中,对当前模型所在的数据库表进行一个查询,将其结果赋值给一个变量list
$list = $this->model->where($pk, 'in', $ids)->select();
//申明一个变量count,令其为0
$count = 0;
//开启事务
Db::startTrans();
try {
//对$list进行循环,并每次循环都将$list的值给$item一次,执行循环是因为可能存在批量删除
foreach ($list as $item) {
//$count=$count+$item->delect()
$count += $item->delete();
//对关联表进行循环删除语句
//$item->together(['stuscore','studentmoney'])->delete();
// 或者
// $item->stuscore()->delete();
// $item->studentmoney()->delete();
//表示对数据库表fa_stuscore与fa_studentmoney中的数据进行删除
$item->together(['stuscore','studentmoney'])->delete();
}
//提交事务
Db::commit();
//判断捕获到的异常类型
} catch (PDOException|Exception $e) {
// 回滚事务(如果事务中的某个点发生故障,对所有表的删、改、写操作(则所有更新)都可以回滚到事务开始之前的状态回滚事务 )
Db::rollback();
//提示错误信息
//$e->getMessage():获取错误信息,并通过echo输出此错误信息。
$this->error($e->getMessage());
}
//如果$count中有值
if ($count) {
//返回成功
$this->success();
}
//提示失败信息
$this->error(__('No rows were deleted'));
}
发表评论 取消回复