table_name="feedback"; //注意,这里父类析构函数一定要放到最下面,否则框架自带的方法不能使用 parent::__construct(); } //自动验证 //array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间]) protected $_validate = array( array('formtype', 'require', '字段类型不能为空!'), array('field', 'require', '字段名称必须填写!'), array('field', 'isFieldUnique', '该字段名称已经存在!', 0, 'callback', 1), array('name', 'require', '字段别名必须填写!'), array('field', '/^[a-z_0-9]+$/i', '字段名只支持英文或数字!', 0, 'regex', 3), ); /** * 验证字段名是否已经存在 * @param type $fieldName * @return boolean false已经存在,true不存在 */ public function isFieldUnique($fieldName) { if (empty($fieldName)) { return true; } if ($this->where(array('field' => $fieldName))->count()){ return false; } return true; } //增加 public function data_add(){ $data=$this->create(); $fieldtype = $data['fieldtype']; //检查字段是否存在 if ($this->field_exists("feedback", $data['field'])) { $this->error = '该字段已经存在!'; return false; } //增加字段 $field = array( 'tablename' => C("DB_PREFIX") .$this->table_name, 'fieldname' => $data['field'], 'fieldlen' => $data['fieldlen'], 'defaultvalue' => $data['defaultvalue'], ); if ($this->addFieldSql($fieldtype, $field)) { //更新htmlcode $data['htmlcode']=$this->createFieldHtmlCode($data); // $fieldid = $this->add($data); if (!$fieldid){ $this->error = '字段信息入库失败!'; //回滚 $this->execute("ALTER TABLE `{$field['tablename']}` DROP `{$field['fieldname']}`"); return false; } } else { $this->error = '数据库字段添加失败!'; return false; } return $fieldid; } //修改模型 public function data_editor(){ $data=$this->create(); if (!$data['field_id']) { $this->error = '缺少字段id!'; return false; } else { $fieldid = $fieldid ? $fieldid : (int) $data['field_id']; } //重置htmlcode $data['htmlcode']=htmlspecialchars_decode($data['htmlcode']); $data['htmlcode']=$this->createFieldHtmlCode($data); //原字段信息 $info = $this->where(array("field_id" => $fieldid))->find(); if (empty($info)) { $this->error = '该字段不存在!'; return false; } //字段类型 if (empty($data['formtype'])) { $data['formtype'] = $info['formtype']; } $field_type = $data['fieldtype']; if (false !== $this->save($data)) { //如果字段名变更 if ($data['field'] && $info['field']) { //检查字段是否存在,只有当字段名改变才检测 if ($data['field'] != $info['field'] && $this->field_exists($this->table_name, $data['field'])) { $this->error = '该字段已经存在!'; //回滚 $this->where(array("field_id" => $fieldid))->save($info); return false; } $field = array( 'tablename' => C("DB_PREFIX") . $this->table_name, 'newfilename' => $data['field'], 'oldfilename' => $info['field'], 'fieldlen' => $data['fieldlen'], 'defaultvalue' => $data['defaultvalue'], ); if (false === $this->editFieldSql($field_type, $field)) { $this->error = '数据库字段结构更改失败!'; //回滚 $this->where(array("field_id" => $fieldid))->save($info); return false; } } } else { $this->error = '数据库更新失败!'; return false; } $cat=M("feedback_cat")->select(); foreach($cat as $v){ $this->updateModelTemp($v["catid"]); } // return $data; } //删除字段 public function data_delete($fieldid) { //原字段信息 $info = $this->where(array("field_id" => $fieldid))->find(); if (empty($info)) { $this->error = '该字段不存在!'; return false; } //完整表名获取 判断主表 还是副表 $tablename = $this->table_name; if ($this->deleteFieldSql($info['field'], C("DB_PREFIX") . $tablename)) { $this->where(array("field_id" => $fieldid))->delete(); } else { $this->error = '数据库表字段删除失败!'; return false; } //modeltemp $cat=M("feedback_cat")->select(); foreach($cat as $v){ $this->updateModelTemp($v["catid"]); } return true; } /** * 重新生成模型表单文件 * @param type $modelId 模型id */ public function updateModelTemp($catid){ $ModelModel=new \Admin\Model\FeedbackCatModel(); $ModelModel->updateModelTemp($catid); } /** * 根据字段类型,删除对应的字段到相应表里面 * @param type $filename 字段名称 * @param type $tablename 完整表名 */ protected function deleteFieldSql($filename, $tablename) { //不带表前缀的表名 $noprefixTablename = str_replace(C("DB_PREFIX"), '', $tablename); if (empty($tablename) || empty($filename)) { $this->error = '表名或者字段名不能为空!'; return false; } if (false === $this->table_exists($noprefixTablename)) { $this->error = '该表不存在!'; return false; } $sql = "ALTER TABLE `{$tablename}` DROP `{$filename}`;"; if (false === $this->execute($sql)) { $this->error = '字段删除失败!'; return false; } return true; } /** * 根据字段类型,增加对应的字段到相应表里面 * @param type $field_type 字段类型 * @param type $field 相关配置 * $field = array( * 'tablename' 表名(完整表名) * 'fieldname' 字段名 * 'maxlength' 最大长度 * 'minlength' 最小值 * 'defaultvalue' 默认值 * 'minnumber' 是否正整数 和整数 1为正整数,-1是为整数 * 'decimaldigits' 小数位数 * ) */ protected function addFieldSql($field_type, $field) { //表名 $tablename = $field['tablename']; //字段名 $fieldname = $field['fieldname']; //长度 $fieldlen = $field['fieldlen']; switch ($field_type) { case "varchar": if (!$fieldlen) { $fieldlen = 255; } $fieldlen = min($fieldlen, 255); $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` VARCHAR( {$fieldlen} ) NOT NULL DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "tinyint": if (!$fieldlen) { $fieldlen = 3; } $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TINYINT( {$fieldlen} ) " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "smallint": $minnumber = intval($minnumber); $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` SMALLINT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "mediumint": $minnumber = intval($minnumber); $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` INT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "int": $minnumber = intval($minnumber); $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` INT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "mediumtext": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` MEDIUMTEXT"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "text": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TEXT"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "date": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` DATE DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "datetime": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "timestamp": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "double": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` DOUBLE NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "float": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` FLOAT NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "bigint": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` BIGINT NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "longtext": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` LONGTEXT"; if (false === $this->execute($sql)) { $this->error = '数据库字段添加失败!'; return false; } break; case "char": $sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` CHAR(255) NOT NULL DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; default: return false; break; } return true; } /** * 执行数据库表结构更改 * @param type $field_type 字段类型 * @param type $field 相关配置 * $field = array( * 'tablename' 表名(完整表名) * 'newfilename' 新字段名 * 'oldfilename' 原字段名 * 'maxlength' 最大长度 * 'minlength' 最小值 * 'defaultvalue' 默认值 * 'minnumber' 是否正整数 和整数 1为正整数,-1是为整数 * 'decimaldigits' 小数位数 * ) */ protected function editFieldSql($field_type, $field) { //表名 $tablename = $field['tablename']; //原字段名 $oldfilename = $field['oldfilename']; //新字段名 $newfilename = $field['newfilename'] ? $field['newfilename'] : $oldfilename; //长度 $fieldlen = $field['fieldlen']; if (empty($tablename) || empty($newfilename)) { $this->error = '表名或者字段名不能为空!'; return false; } switch ($field_type) { case 'varchar': //最大值 if (!$maxlength) { $maxlength = 255; } $maxlength = min($maxlength, 255); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` VARCHAR( {$maxlength} ) NOT NULL DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'tinyint': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` TINYINT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'smallint': $minnumber = intval($minnumber); $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` SMALLINT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT '{$defaultvalue}' DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'mediumint': $minnumber = intval($minnumber); $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` MEDIUMINT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT '{$defaultvalue}' DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'int': $minnumber = intval($minnumber); $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` INT " . ($minnumber >= 0 ? 'UNSIGNED' : '') . " NOT NULL DEFAULT '{$defaultvalue}' DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'mediumtext': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` MEDIUMTEXT"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'text': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` TEXT"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'date': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` DATE DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'datetime': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case 'timestamp': $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "double": $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` DOUBLE NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "float": $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` FLOAT NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "bigint": $defaultvalue = intval($defaultvalue); $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` BIGINT NOT NULL DEFAULT 0"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "longtext": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` LONGTEXT"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; case "char": $sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` CHAR(255) NOT NULL DEFAULT ''"; if (false === $this->execute($sql)) { $this->error = '字段结构更改失败!'; return false; } break; default: $this->error = "字段类型" . $field_type . "不存在相应信息!"; return false; break; } return true; } /* * 创建字段html代码 */ public function createFieldHtmlCode($data){ if($data['field_id']){ $info=M("feedback_field")->find($data['field_id']); //当字段类型 and 宽度 and 高度 and 默认值 未改变的时候htmlcode等于提交过来的,否则执行重新生成动作 if($info['field']==$data['field']&&$info['name']==$data['name']&&$info['formtype']==$data['formtype']&&$info['formwidth']==$data['formwidth']&&$info['formheight']==$data['formheight']&&$info['defaultval']==$data['defaultval']&&$info['tips']==$data['tips']){ $htmlcode=$data['htmlcode']; }else{ $htmlcode=$this->FieldHtmlCodeReplace($data); } }else{ $htmlcode=$this->FieldHtmlCodeReplace($data); } return $htmlcode; } /* * 替换字段类型的代码 * */ public function FieldHtmlCodeReplace($rs){ //获取表单类型的模板文件 $field_temp= file_get_contents(APP_PATH.self::modelFieldPath.$rs['formtype'].".php"); //内容替换 $field_temp= str_replace("{modelFieldTemp_field}",$rs['field'],$field_temp); $field_temp= str_replace("{tips}",$rs['tips'],$field_temp); $field_temp= str_replace("{defaultval}",$rs['defaultval'],$field_temp); //宽度 if($rs['formwidth']){ $style_formwidth="width:".$rs['formwidth']."px;"; }else{ $style_formwidth=""; } $field_temp= str_replace("{style_formwidth}",$style_formwidth,$field_temp); //高度 if($rs['formheight']){ $style_formheight="height:".$rs['formheight']."px;"; }else{ $style_formheight=""; } $field_temp= str_replace("{style_formheight}",$style_formheight,$field_temp); //编辑器高度 宽度替换(因为编辑器只调用数值,不需要css样式) $field_temp= str_replace("{formwidth}",$rs['formwidth'],$field_temp); $field_temp= str_replace("{formheight}",$rs['formheight'],$field_temp); //checkbox radio select选项替换 $checkbox_option=""; if($rs['formtype']=="checkbox"||$rs['formtype']=="radio"||$rs['formtype']=="select"){ if($rs['defaultval']){ $defaultval=explode("\r\n",$rs['defaultval']); foreach($defaultval as $v){ $dufault_arr=explode(":",$v); $option_arr=explode("==",$dufault_arr[0]); $select_checked=$dufault_arr[1]=="default"?'':"";//select 默认选择中的 $checked_default=$dufault_arr[1]=="default"?'':"";//checked radio 默认选择中的 $option_name=trim($option_arr[0]);//字段名称 $option_value=trim($option_arr[1]==""?$option_arr[0]:$option_arr[1]);//字段值 为空时=名称 if($rs['formtype']=="checkbox"){ $checkbox_option.=''; } if($rs['formtype']=="radio"){ $checkbox_option.=''; } if($rs['formtype']=="select"){ $checkbox_option.=''; } } } } $field_temp= str_replace("{select_option}",$checkbox_option,$field_temp); return $field_temp; } }