1.自关联
2.sql语句
CREATE TABLE IF NOT EXISTS `menu`(
`m_title` varchar(255) NOT NULL COMMENT "菜单名",
`isshow` int(20) COMMENT "显示",
`icon` varchar(255) COMMENT "图标",
`isexpand` int(20) COMMENT "展开",
`m_parent_id` int(20) COMMENT "上级栏目",
FOREIGN KEY (`m_parent_id`) REFERENCES `menu`(`id`) ,
`ischecked` int(20) COMMENT "选中",
`m_url` varchar(255) COMMENT "链接",
`id` INT(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`))ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜单';3.表结构(注意:有外键约束)
4.form提交到Controler

5.D("Menu")->create()->add(),插入失败产生如下sql语句
'INSERT INTO `menu` (`m_title`,`isshow`,`icon`,`isexpand`,`m_parent_id`,`ischecked`,`m_url`,`id`) VALUES ('xxxxx',0,'',0,0,0,'',0)'6.将产生的sql直接拿到mysql运行如下,外键约束错误
说明:这里错误的原因是,tp在拼接sql的时候没有将有外键约束的情况考虑下去,外键列m_parent_id在传空值或者0的时候应该将其值转为NULL,来完成更新,而这里tp却是转为空字符串“”,导致mysql在做外键检测的时候报错。
错误位置:
Model里的autoOperation方法里的判断是
case 'ignore': // 为空忽略
if($auto[1]===$data[$auto[0]])
unset($data[$auto[0]]);到了Db这个类里时候做只是简单的implode,啥都没处理,代码如下 $sql = ($replace?'REPLACE':'INSERT').' INTO '.$this->parseTable($options['table']).' ('.implode(',', $fields).') VALUES ('.implode(',', $values).')';解决方案:对前台传入的值,经过tp的create函数后,自己多做一步校验,将传入的值做数据库类型的强转,对于空值返回一个NULL
/**
*没有宽度的数据库类型转php类型
*/
function convert_type_name($type){
switch($type)
{
case "int" :
case "smallint":
case "tinyint":
case "mediumint":
case "bigint":
return "int";
case "decimal":
case "double":
case "float":
return "float";
case "char":
case "varchar":
case "tinytext":
case "text":
case "blob":
case "mediumtext":
case "longtext":
case "longblob":
return "string";
case "date":
case "datetime":
case "timestamp":
return "date";
case "time":
return "time";
default:
return "string";
}
}
/**
* 基于数据库类型提取php的类型
*/
function convert_dbtype_to_phptype($type){
if(preg_match("#([\w]*)(\([\d,]*\))#",$type,$matchs)){
return $matchs[1];
}
return $type;
}
/**
* 将值强转为数据库数据类型
*/
function convert_parm_to_type($type,$value){
$type=convert_type_name(convert_dbtype_to_phptype($type));
if($value){
switch($type){
case "int":
return (int)($value);
break;
case "float":
return (double)($value);
break;
case "string":
return (string)($value);
break;
case "date":
case "time":
return (string)($value);
break;
default:
exit('输入非法值'.$value);
break;
}
}else{
return NULL;
}
} 最佳答案