Thinkphp 3.23 视图模板中使用数组作为查询条件出现的错误
探索
整理一个基于 thinkphp 3.23 的 crm 系统,可能因为本地 PHP 版本较高的原因,本地测试出现很多 bug。
页面报错:Column not found: 1054 Unknown column 'A' in 'where clause'
,后面跟了一大堆的 trace 信息。通过排查,找到最终的错误文件,在模板文件中:
<php>
if(isset($_REQUEST['time1']) && $_REQUEST['time1'] != ''&&isset($_REQUEST['time2']) && $_REQUEST['time2'] != '') {
$map['shijian'] = array(array('egt',I('time1').' 00:00:00'),array('elt',I('time2').' 59:59:59'));
}
$where['bianhao'] = array("eq",$v['bianhao']);
$map['_complex'] = $where;
echo M('rukus')->where($map)->sum('shuliang');
$where="";
$map="";
</php>
注意:代码在 html 文件中,使用了内置标签 <php></php>
,并不是正常的 PHP 代码,需要编译解析。
整个查询使用了复合查询,复合查询的前半部分是一个区间查询,假设 time1
、time2
为 2019-11-13
,$v['bianhao']
为 n123
,查询条件为:
( ( shijian >= '2019-11-13 00:00:00' ) AND ( shijian <= '2019-11-13 59:59:59' )) AND ( bianhao = 'n123' )
当 time1、time2 不存在时,查询条件为:
bianhao = 'n123'
从正常的分析角度,写法没有问题,但结果还是报错了。网上查了一下这个错误,大部分报错情况是因为条件中的某个字段值为字符串,但没有添加上引号包裹。举个例子: bianhao = n123
。
通过测试确定报错点在 $where['bianhao'] = array("eq",$v['bianhao']);
。
查看 runtime 下的访问日志:
...
SQL: SELECT SUM(shuliang) AS tp_sum FROM `xy_rukus` WHERE `bianhao` = 'ddd' LIMIT 1 [ RunTime:0.0000s ]
...
ERR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'A' in 'where clause'
从 SQL 语句上并不能看出端倪,先放一边。
尝试将 $where['bianhao'] = array("eq",$v['bianhao']);
改成 $where['bianhao'] = $v['bianhao']
,依然报错。
也就是说,(在视图模板中字符串赋值)数组查询或者表达式查询都不可用。考虑使用字符串条件:"biaohao = '$v[bianhao]'"
。所以条件改成:
...
$where['_string'] = " bianhao = '$v[bianhao]' ";
$map['_complex'] = $where;
...
结果还是不行。见鬼!!!
解决
使用 M('rukus')->->getLastSql();
查看发现,错误在输出 sql 之前,也就是执行查询的语句,此路不同。
设置断点,反复查了一会儿,发现 $map 值在传入的时候,变成了 'A',这是什么情况???
通过在语句之间插入输出语句 echo px;var_dump($map);
,检查 $map 和 $where 在执行查询之前的值。
最终发现,$map 初始值设为了空字符串,而在 $map['shijian'] = array(array('egt',I('time1').' 00:00:00'),array('elt',I('time2').' 59:59:59'));
赋值后,值变成了 A
。
思虑再三,猜测是初始值的设置的问题(虽然还是一肚子疑问,PHP 不是弱类型语言吗,变量赋值应该会自动转换类型啊)。将 $where 和 $map 初始值设为 array()
,再次测试,完美,不再有任何问题。
总结
这个错误是由于 PHP 高版本变量类型转换不再自动转换造成的,初始化时为字符串类型,之后转变为数组类型失败,保留了一个 A
字符,造成了后续的 SQL 查询问题。
一开始猜想是 thinkphp 在视图模板中的 PHP 代码需要解析转换,可能使用数组条件添加的字符串类型的字段值,不能够正常地添加引号。没想到是 PHP 高版本新特性导致的。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。