您好,欢迎访问木子天禾科技官网!
17319297980
15934152105
北京软件开发公司_山西软件开发公司_木子天禾科技官网
联系我们

北京软件开发公司_山西软件开发公司_木子天禾科技官网

地址:山西省太原市小店区恒大未来城5-1711
手机:15934152105

咨询热线17319297980

Thinkphp3.1修改数据表后,表字段获取失败原因

发布时间:2020-01-08 11:26人气:

一、案例
 
因为公司项目比较早,因此即使到了如今,THINKPHP(以下简称TP)都出到5.0+,我们依然用着TP3.1,来维护和开发迭代原有的项目。
在开发过程中,我们会对数据表进行字段更改,然后用where条件去查询相应的数据。然而在TP框架中,有时候会出现明明在数据表中有的字段,却在打印的sql语句中莫名丢失。
假设我有一张A表,字段为
id,name,is_del,create_time。
1.0.0版本的功能实现简单的查询操作语句为:
M(A)->where(['is_del'=>0])->limit(20)->select();
之后客户修改了需求,在A表中新增了status字段,用来标示数据的状态,并也要实现筛选,我称之为1.0.1版本。
但是在1.0.1版本中,我用查询语句
M(A)->where(['is_del'=>0,'status'=>1])->limit(20)->select()
去查询时,发现并没有根据status状态来筛选,当我打印出sql语句,发现语句如下:
SELECT * FROM A WHERE `is_del`=0 LIMIT 20;
没错,status并没有进入到查询条件,我反复对比了数据表的字段,甚至怀疑是否是因为关键词引起了冲突,在我改名也好,用$condition['status']=array('eq',1);这样的方式也好,sql语句中还是没有出现status查询条件。而我用以下2种方式时,却能筛选出想要的数据:
1.M(A)->where('is_del=0 AND status=1')->limit(20)->select();
2.M(A)->query('SELECT * FROM A WHERE `is_del`=0 AND `status`=1 LIMIT 20');
这一定是TP想玩死我吧。
虽然这种方式能够解决燃眉之急,但以后1.X.X版本有多个条件,不至于让程序员用一个字符串去拼接出查询语句吧,这样就有违使用框架的初衷了。
会不会是TP读不到这个字段?既然有了怀疑,那就大胆地尝试一下。
M(A)->getDbFields();
打印以后,果然只有1.0.0版本的4个字段。TP就是想玩死我吧!
 
二、解决方案一
 
在我翻阅TP手册的时候,看到了一个DB参数:
DB_FIELDS_CACHE,是否开启数据表字段缓存,默认为true
于是我在配置中,加了一行
return [
...
'DB_FIELDS_CACHE' => false,
...
]
再去打印sql语句:
SELECT * FROM A WHERE `is_del`=0 AND `status`=1 LIMIT 20;
果然是因为数据表字段缓存的缘故,但是如果关闭了这个配置,那以后所有涉及到表操作的,都要去连接数据表来获取该表所拥有的字段,这样会加大服务器的资源消耗,该方式也不是万全之策。
既然有缓存,那一定产生了缓存文件,于是我在~Runtime/Data/_fields下面的找到了A表的文件db.A.php。
该文件格式如下:
return [
0=>id,
1=>name,
2=>is_del,
3=>create_time,
'_autoinc' => true,
'_pk' => 'id',
'_type' =>[
'id'=>'int(10)',
'name'=>'varchar(50)',
'is_del'=>'tinyint(1)',
'create_time'=>'int(10)',
]
]
可以看到,这个文件中并没有status字段。因此,只要将该字段添加进该文件中,便大功告成。
然后打印sql语句和数据,都显示正常数据。
至此,在新增或修改表字段后,sql中获取不到该字段的问题得到圆满解决。
以下引用另一篇博客的话:
当然你也可以在模型类里面手动定义数据表字段的名称,可以避免IO加载的效率开销,在模型类里面添加fields属性即可,定义格式如下:
class AModel extends Model{
protected $fields = [
'id',
'name',
'is_del',
'status',
'create_time',
'_pk'=>'id',
'_autoinc'=>true
]
}
其中_pk 表示主键字段名称 _autoinc 表示主键是否自动增长类型
 
三、解决方案二(最简单)

打开debug模式,重新生成数据缓存即可。
 
四、总结
 
该问题是偶然发现的,因为我们的一个项目放在客户自己的服务器上,在我们自己服务器上从来没出现过这样的问题,也有可能跟服务器的环境也有关。但这也暴露了我们在开发的过程中,不够严谨的毛病。
该问题的主要解决方案就是修改数据表的缓存文件或关闭数据表字段缓存。
在今后的工作中,仍需要多学习,多思考。
 

推荐资讯

17319297980