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"?'=$r?"":"selected"?>':"";//select 默认选择中的
$checked_default=$dufault_arr[1]=="default"?'=$r?"":"checked"?>':"";//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;
}
}