thinkPHP使用中踩的坑,记录一下(不停更)
版本3.2.3
1、数据库操作中的连贯操作table(),在查询的时候可以切换表,但是在插入,更新的时候请不要使用。例如
D('user')->table('auth')->add($data);
操作会出问题,因为插入的时候会把非user表的字段删除
2.数据库操作的create(),如果使用了框架的自动验证功能,在create()时会验证字段的合法性,有时候我们会多次create,进行批量添加或者修改,这时候会出问题。查看源码,发现是因为里面的$error属性没有重置。设置Model的$patchValidate为true是一种办法,但是会导致返回的错误不再是一个字符串,而是数组,并且即使已经有不合法的字段了,还是会继续验证其他字段,解决办法是
//重写create方法,每次create,清空error public function create($data = '', $type = '') { $this->error = array(); return parent::create($data, $type); // TODO: Change the autogenerated stub }
3.数据库操作的save()方法,如果在save()方法前面有使用getByxxx()或者find()这些方法的话,一定要记得给save()方法手动传$data数据。或者连贯操作->data($data)->save(),否则当前要添加或保存的数据会变成刚刚查询到的。查看源码可知道原因:
解决办法:
//更新失败,因为save()的数据是旧数据 $Model->create($data); $oldData = $Model->getById($data['id']); $updateRes = $Model->save(); //更新成功 $Model->create($data); $oldData = $Model->getById($data['id']); $updateRes = $Model->save($data);//或者用下面那一行 //$updateRes = $Model->data($data)->save();
4、字段缓存问题
首先是数据库表设计更新以后会有所影响;此外还有个问题,由于我的项目有多个模块,恰好两个模块中有两个模型名都一样,经常出现其中一个模块不能正常添加和修改的情况
后来看了源码才找到原因:字段缓存的文件名是"数据库名+表前缀+模型名",导致两个模型读取的缓存文件名是一样的
解决办法:
(1)关闭字段缓存
(2)不同模块设置不同的表前缀
(3)修改模型的名称
个人觉得TP框架的这个缓存机制实在不太合理,模型里面明明都有指定tableName,没必要根据表前缀和模型名去缓存字段
5、S()方法缓存失败
在命令行模式下,执行定时脚本发现S()方法缓存失败,首先想到的就是权限问题,但是检查以后还是不行,后来一步步找到源码,发现缓存文件的路径是C('DATA_CACHE_PATH'),由于APP_PATH是相对路径,导致这个也是相对路径
然而,用crontab执行php脚本,代码里面一定要用绝对路径,否则很容易出错。把APP_PATH设置为__DIR__.'/Application/',问题解决
6、这条不是坑,是个小提示
我们在添加数据时,有时候希望如果已经存在了就更新,通常会用ON DUPLICATE KEY UPDATE语句,之前一直以为thinkPHP没有这个方法,只能通过自己手动拼接sql语句。
这几天看了一下Mysql.class.php的源码发现是支持的,只是官方文档没有给出来。
$addRes = $Model->add($addData,array(),'cpu,mem,hard_disk');
通常我们只会传第一个参数,第二个参数是配置,默认是空数组,第三个参数就是ON DUPLICATE KEY UPDATE要更新的字段。支持字符串和数组的形式。对于addAll()方法也是一样的。