526 lines
22 KiB
PHP
526 lines
22 KiB
PHP
<?php
|
||
namespace Admin\Model;
|
||
use Think\Model;
|
||
class TableFieldModel extends Model{
|
||
//自动验证
|
||
//array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间])
|
||
protected $_validate = array(
|
||
array('table_id', 'require', '请选择数据表!'),
|
||
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('table_id' =>I("table_id"), 'field' => $fieldName))->count()){
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* 根据模型ID,返回表名
|
||
* @param type $table_id
|
||
* @param type $table_id
|
||
* @return string
|
||
*/
|
||
protected function getTbName($table_id, $issystem = 1) {
|
||
//表名获取
|
||
$table_name = M("table")->where(array("table_id"=>$table_id))->getField("table_name");
|
||
$table_name="cms_".$table_name;
|
||
//完整表名获取 判断主表 还是副表
|
||
$table_name = $issystem ? $table_name : $table_name . "_data";
|
||
return $table_name;
|
||
}
|
||
//增加
|
||
public function data_add(){
|
||
$data=$this->create();
|
||
//数据表id
|
||
$table_id = $data['table_id'];
|
||
$fieldtype = $data['fieldtype'];
|
||
//完整表名获取 判断主表 还是副表
|
||
$table_name = $this->getTbName($table_id, $data['issystem']);
|
||
if (!$this->table_exists($table_name)) {
|
||
$this->error = '数据表不存在!';
|
||
return false;
|
||
}
|
||
//检查字段是否存在
|
||
if ($this->field_exists($table_name, $data['field'])) {
|
||
$this->error = '该字段已经存在!';
|
||
return false;
|
||
}
|
||
|
||
//增加字段
|
||
$field = array(
|
||
'tablename' => C("DB_PREFIX") . $table_name,
|
||
'fieldname' => $data['field'],
|
||
'fieldlen' => $data['fieldlen'],
|
||
'defaultvalue' => $data['defaultvalue'],
|
||
);
|
||
if ($this->addFieldSql($fieldtype, $field)) {
|
||
//更新htmlcode
|
||
$TableModel=new \Admin\Model\TableModel();
|
||
$data['htmlcode']=$TableModel->createFieldHtmlCode($data);
|
||
$data['memberhtmlcode']=$TableModel->createMemberFieldHtmlCode($data);
|
||
//
|
||
$fieldid = $this->add($data);
|
||
if ($fieldid) {
|
||
return $fieldid;
|
||
} else {
|
||
$this->error = '字段信息入库失败!';
|
||
//回滚
|
||
$this->execute("ALTER TABLE `{$field['tablename']}` DROP `{$field['fieldname']}`");
|
||
return false;
|
||
}
|
||
} else {
|
||
$this->error = '数据库字段添加失败!';
|
||
return false;
|
||
}
|
||
}
|
||
//修改
|
||
public function data_editor(){
|
||
$data=$this->create();
|
||
if (!$data['field_id']) {
|
||
$this->error = '缺少字段id!';
|
||
return false;
|
||
} else {
|
||
$field_id = $field_id ? $field_id : (int) $data['field_id'];
|
||
}
|
||
//重置htmlcode
|
||
$TableModel=new \Admin\Model\TableModel();
|
||
$data['htmlcode']=htmlspecialchars_decode($data['htmlcode']);
|
||
$data['htmlcode']=$TableModel->createFieldHtmlCode($data);
|
||
//投稿的
|
||
$data['memberhtmlcode']=htmlspecialchars_decode($data['memberhtmlcode']);
|
||
$data['memberhtmlcode']=$TableModel->createMemberFieldHtmlCode($data);
|
||
//原字段信息
|
||
$info = $this->where(array("field_id" => $field_id))->find();
|
||
if (empty($info)){
|
||
$this->error = '该字段不存在!';
|
||
return false;
|
||
}
|
||
//字段主表副表不能修改
|
||
unset($data['issystem']);
|
||
//字段类型
|
||
if (empty($data['formtype'])) {
|
||
$data['formtype'] = $info['formtype'];
|
||
}
|
||
//模型id
|
||
$table_id = $info['table_id'];
|
||
$field_type = $data['fieldtype'];
|
||
//完整表名获取 判断主表 还是副表
|
||
$tablename = $this->getTbName($table_id, $info['issystem']);
|
||
if (!$this->table_exists($tablename)) {
|
||
$this->error = '数据表不存在!';
|
||
return false;
|
||
}
|
||
|
||
if (false !== $this->save($data)) {
|
||
//如果字段名变更
|
||
if ($data['field'] && $info['field']) {
|
||
//检查字段是否存在,只有当字段名改变才检测
|
||
if ($data['field'] != $info['field'] && $this->field_exists($tablename, $data['field'])) {
|
||
$this->error = '该字段已经存在!';
|
||
//回滚
|
||
$this->where(array("field_id" => $field_id))->save($info);
|
||
return false;
|
||
}
|
||
$field = array(
|
||
'tablename' => C("DB_PREFIX") . $tablename,
|
||
'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" => $field_id))->save($info);
|
||
return false;
|
||
}
|
||
//根据table_id查询model表,并更新modeltemp
|
||
$model=M("model")->where(array("table_id"=>$table_id))->select();
|
||
$ModelModel=new \Admin\Model\ModelModel();
|
||
foreach($model as $v){
|
||
$ModelModel->updateModelTemp($v["modelid"]);
|
||
}
|
||
}
|
||
} else {
|
||
$this->error = '数据库更新失败!';
|
||
return false;
|
||
}
|
||
//
|
||
|
||
//
|
||
return $data;
|
||
}
|
||
//删除字段
|
||
public function data_delete($field_id,$systemfield) {
|
||
//原字段信息
|
||
$info = $this->where(array("field_id" => $field_id))->find();
|
||
if (empty($info)) {
|
||
$this->error = '该字段不存在!';
|
||
return false;
|
||
}
|
||
//模型id
|
||
$table_id = $info['table_id'];
|
||
//完整表名获取 判断主表 还是副表
|
||
$tablename = $this->getTbName($table_id, $info['issystem']);
|
||
if (!$this->table_exists($tablename)) {
|
||
$this->error = '数据表不存在!';
|
||
return false;
|
||
}
|
||
//判断是否允许删除
|
||
if (in_array($info['field'],$systemfield)){
|
||
$this->error = '系统字段不允许被删除!';
|
||
return false;
|
||
}
|
||
if ($this->deleteFieldSql($info['field'], C("DB_PREFIX") . $tablename)) {
|
||
$this->where(array("field_id" => $field_id, "table_id" => $table_id))->delete();
|
||
//根据table_id查询model表,并更新modeltemp
|
||
$model=M("model")->where(array("table_id"=>$table_id))->select();
|
||
$ModelModel=new \Admin\Model\ModelModel();
|
||
foreach($model as $v){
|
||
$ModelModel->updateModelTemp($v["modelid"]);
|
||
}
|
||
} else {
|
||
$this->error = '数据库表字段删除失败!';
|
||
return false;
|
||
}
|
||
return true;
|
||
|
||
}
|
||
/**
|
||
* 根据字段类型,删除对应的字段到相应表里面
|
||
* @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} ) 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} ) 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( {$fieldlen} ) 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 ( {$fieldlen} ) 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 ( {$fieldlen} ) 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( {$fieldlen} ) NOT NULL DEFAULT 0";
|
||
if (false === $this->execute($sql)) {
|
||
$this->error = '数据库字段添加失败!';
|
||
return false;
|
||
}
|
||
break;
|
||
case "bigint":
|
||
$sql = "ALTER TABLE `{$tablename}` ADD `{$fieldname}` BIGINT( {$fieldlen} ) 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( {$fieldlen} ) 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 (!$fieldlen) {
|
||
$fieldlen = 255;
|
||
}
|
||
$fieldlen = min($fieldlen, 255);
|
||
$sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` VARCHAR( {$fieldlen} ) DEFAULT ''";
|
||
if (false === $this->execute($sql)) {
|
||
$this->error = '字段结构更改失败!';
|
||
return false;
|
||
}
|
||
break;
|
||
case 'tinyint':
|
||
$sql = "ALTER TABLE `{$tablename}` CHANGE `{$oldfilename}` `{$newfilename}` TINYINT( {$fieldlen} ) 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 ( {$fieldlen} ) 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 ( {$fieldlen} ) 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 ( {$fieldlen} ) 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(" . $minnumber . ") 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(" . $fieldlen . ") DEFAULT ''";
|
||
if (false === $this->execute($sql)) {
|
||
$this->error = '字段结构更改失败!';
|
||
return false;
|
||
}
|
||
break;
|
||
default:
|
||
$this->error = "字段类型" . $field_type . "不存在相应信息!";
|
||
return false;
|
||
break;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
}
|