🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 【字段编辑·思路分析】 ### 思路分析 > 1、更改字段编辑模板 2、控制器查询该字段信息,并分配到模板 3、重点解决参数设置在模板中自动加载 4、修改处理方法(控制器负责逻辑判断;模型负责业务处理) 如果字段名称不修改,则修改models_field表,否则,还需修改对应附表的字段名称 ### 注意事项 1、字段类型是不能修改的,只能改属性; 2、变量中嵌套变量是不能显示的,要用php原生写法; ~~~ <?php echo $setting['defaultvalue']; ?> <?php if ($setting['ispassword']) echo 'checked'; ?> <?php if (!$setting['ispassword']) echo 'checked'; ?> ~~~ ### 优化代码 > 1、完善无限极分类 2、添加和修改,判断是否重名条件是不一样的(字符串查询,预处理机制,安全) 3、字段编辑条件判断(字段名和字段别名是否重名) 4、字段删除时,判断附表中是否存在该字段,存在则删除(通用函数field_exists) ## 模型(字符串查询,预处理机制) > 判断模型是否存在,采用字段串条件查询,配合预处理机制 ### 局部代码 ~~~ use app\admin\model\ModelsField as ModelsFieldModel; $models = new ModelsModel; $models::where("id!=:id AND (tablename=:tablename OR name=:name)") ->bind([ 'id'=>$id, 'tablename'=>$data['tablename'], 'name'=>$data['name']] )->count(); ~~~ ### 模型编辑完整代码 ~~~ //编辑模型 public function edit($tab=1,$id=0){ if(request()->isPost()){ $data = input('post.'); if(trim($data['tablename'])==''){ return error('模型表名不能为空!'); exit; } $models = new ModelsModel; //判断模型是否存在,采用字段串条件查询,配合预处理机制 if($models::where("id!=:id AND (tablename=:tablename OR name=:name)") ->bind(['id'=>$id,'tablename'=>$data['tablename'],'name'=>$data['name']])->count()){ return error('模型已经存在!'); exit; } //获取原数据库表名 $oldTableName = Db::name('models')->where('id',$id)->value('tablename'); //当前提前新表名 $newTableName = trim($data['tablename']); if($models->allowField(true)->isUpdate()->save($data)){ //判断数据库表名是否做了修改 if($oldTableName!=$newTableName){ if($models->editTableName($oldTableName,$newTableName)){ return success('模型编辑成功!',url('index',['tab'=>1])); }else{ return error('模型编辑失败!'); } }else{ return success('模型编辑成功!',url('index',['tab'=>1])); } }else{ return error('模型信息未变动或修改失败!'); } } } ~~~ ## 模板中自动加载模板,变量赋值 #### 列表模板中代码:index.html ~~~ <div id="setting"> {$fieldinfo.setting} </div> ~~~ 其中,{$fieldinfo.setting}是序列化代码,不是需要的内容 #### 编辑模板中代码:field_edit.html ~~~ <div class="col-md-12"> <div class="form-group"> <label class="col-sm-1 control-label">默认值</label> <div class="col-sm-11"> <input type="text" name="setting[defaultvalue]" class="form-control" value="<?php echo $setting['defaultvalue']; ?>"> </div> </div> <div class="form-group"> <label class="col-sm-1 control-label">密码框</label> <div class="col-sm-11"> <input type="radio" name="setting[ispassword]" value="1" <?php if ($setting['ispassword']) echo 'checked'; ?>> 是 <input type="radio" name="setting[ispassword]" value="0" <?php if (!$setting['ispassword']) echo 'checked'; ?>> 否 </div> </div> </div> ~~~ #### 控制器中代码 > 1、反序列化setting值 ~~~ //获取当前字段信息 $fieldinfo = Db::name('models_field')->where('id',$fid)->find(); $setting = unserialize($fieldinfo['setting']);//替换前参数值反序列化 $this->assign('setting',$setting); ~~~ > 读取字段编辑模板(编辑模板与添加模板一一对应) > 任务:A添加(读取)模板;B替换模板中的变量(默认值) ~~~ //打开缓冲区 ob_start(); //引入字段编辑模板文件 include APP_PATH . 'admin/view/models_field/setting/' . $fieldinfo['formtype'] . '/field_edit.html'; $data_setting = ob_get_contents(); //清空缓冲区并关闭输出缓冲 ob_end_clean(); $fieldinfo['setting'] = $data_setting; //替换后参数值 $this->assign('fieldinfo',$fieldinfo); ~~~ > 3、修改代码 ~~~ public function edit(){ //实例化字段模型 $modelsfield = new ModelsFieldModel; if(request()->isPost()){ if($modelsfield->editField(input('post.'))){ return success('字段编辑成功!',url('index',array('id'=>input('post.modelid'),'tab'=>1))); }else{ return error('字段修改失败!'); } } } ~~~ #### 模型中代码 ~~~ /** * [editField 编辑字段实现] * @param [array] $data [提交的表单信息] * @return [type] [成功返回true,失败返回false] */ public function editField($data){ //对字段参数进行序列化 $setting = $data['setting']; $data['setting'] = serialize($setting); if(isset($setting[defaultvalue])){ $defaultvalue = $setting[defaultvalue]; } //模型ID $modelid = $data['modelid']; //根据模型ID获取模型名 $modelname = Db::name('models')->where('id',$modelid)->value('tablename'); //获取数据表前缀 $dbPrefix = config('database.prefix'); //获取副表名 $tablename = $dbPrefix.$modelname; //字段名 $fieldname = $data['field']; //获取原字段名称 $oldFieldname = Db::name('models_field')->where('id',$data['id'])->value('field'); $modelsfield = new ModelsField; if($modelsfield->allowField(true)->isUpdate()->save($data)){ //判断字段名有无修改,修改则需要改副表中相应字段名 if($oldFieldname!=$fieldname){ //修改副表字段名 switch($data['formtype']){ case "text": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '{$defaultvalue}' "; Db::execute($sql); break; case "textarea": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` TEXT"; Db::execute($sql); break; case "editor": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` TEXT"; Db::execute($sql); break; case "box": if($setting[fieldtype]=='varchar'){ $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` VARCHAR(1) NOT NULL DEFAULT '{$defaultvalue}' "; }elseif($setting[fieldtype]=='int'){ $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` TINYINT(1) NOT NULL DEFAULT '{$defaultvalue}' "; } Db::execute($sql); break; case "image": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '' "; Db::execute($sql); break; case "images": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` TEXT"; Db::execute($sql); break; case "number": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` INT"; Db::execute($sql); break; case "box": if($setting[fieldtype]=='date'){ $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` DATE"; }elseif($setting[fieldtype]=='datetime'){ $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` DATETIME"; } Db::execute($sql); break; case "downfile": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '' "; Db::execute($sql); break; case "downfiles": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldFieldname}` `{$fieldname}` TEXT"; Db::execute($sql); break; } return true; } return true; }else{ return false; //编辑失败 } } ~~~ ## 相关知识 ### 原生态更改数据表某字段值 ~~~ UPDATE tp_models_field SET issystem=0 WHERE modelid=35; ~~~ ### 原生态修改数据表字段名称 ~~~ ALTER TABLE `ps_test` DROP COLUMN `{$info['field']}` ; ~~~ ### 原生态添加数据表字段名称 ~~~ ALTER TABLE `ps_test` ADD `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '{$defaultvalue}'; ~~~ ### 转数组格式 ~~~ 方法一:$settings = array('setting'=>$data_setting); 方法二:$settings['setting'] = $data_setting;(推荐) ~~~ ## 公共函数 ### 判断数据表是否存在 ~~~ /** * [table_exists 检测数据表是否存在] * @param string $tablename [表名,不含前缀] * @return [bool] [存在返回true,不存在返回false] */ function table_exists($tablename='') { //获取所有数据表名 $tables = []; $data = Db::query('SHOW TABLES'); foreach ($data as $value) { $tables[] = $value['Tables_in_'.config('database.database')]; } //获取表前缀 $dbPrefix = config('database.prefix'); //当前的表名 $tablename=$dbPrefix.$tablename; if(in_array($tablename,$tables)){ return true; //存在 }else { return false; //不存在 } } ~~~ ### 判断字段是否存在 ~~~ /** * [field_exists 检测数据表字段是否存在] * @param string $tablename [表名,不含前缀] * @param string $field [字段名] * @return [bool] [存在返回true,不存在返回false] */ function field_exists($tablename='', $field='') { //获取表前缀 $dbPrefix = config('database.prefix'); //先判断数据表是否存在 if(table_exists($tablename)){ $fieldArray = Db::query("Describe `{$dbPrefix}{$tablename}` `{$field}` ;"); if(is_array($fieldArray[0])){ return true; //存在 }else { return false; //不存在 } }else { return false; //不存在 } } ~~~ ## 添加字段模型处理代码 ~~~ //添加字段 public function addField($data){ //对字段参数进行序列化 $setting = $data['setting']; $data['setting'] = serialize($setting); if(isset($setting[defaultvalue])){ $defaultvalue = $setting[defaultvalue]; } //模型ID $modelid = $data['modelid']; //根据模型ID获取模型名 $modelname = Db::name('models')->where('id',$modelid)->value('tablename'); //获取数据表前缀 $dbPrefix = config('database.prefix'); //获取副表名 $tablename = $dbPrefix.$modelname; //字段名 $fieldname = $data['field']; //检测当前模型下字段名是否重复 $count = Db::name('models_field')->where('field',$fieldname)->where('modelid',$modelid)->count(); if($count){ return -1; }else{ //添加新字段 $modelsfield = new ModelsField; if($modelsfield->allowField(true)->save($data)){ //添加副表字段 switch($data['formtype']){ case "text": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '{$defaultvalue}' "; Db::execute($sql); break; case "textarea": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TEXT"; Db::execute($sql); break; case "editor": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TEXT"; Db::execute($sql); break; case "box": if($setting[fieldtype]=='varchar'){ $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` VARCHAR(1) NOT NULL DEFAULT '{$defaultvalue}' "; }elseif($setting[fieldtype]=='int'){ $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TINYINT(1) NOT NULL DEFAULT '{$defaultvalue}' "; } Db::execute($sql); break; case "image": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '' "; Db::execute($sql); break; case "images": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TEXT"; Db::execute($sql); break; case "number": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` INT"; Db::execute($sql); break; case "box": if($setting[fieldtype]=='date'){ $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` DATE"; }elseif($setting[fieldtype]=='datetime'){ $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` DATETIME"; } Db::execute($sql); break; case "downfile": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` VARCHAR(255) NOT NULL DEFAULT '' "; Db::execute($sql); break; case "downfiles": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TEXT"; Db::execute($sql); break; } return 1; }else{ return -2; } } } ~~~