tp3.2.2 关联插入bug

浏览:767 发布日期:2014/05/09 分类:求助交流 关键字: tp3.1.2 关联插入bug
情景:
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;
        }
        
    }
最佳答案
评论( 相关
后面还有条评论,点击查看>>