使用xdebug调试PHP程序(实例)

使用xdebug调试PHP程序(实例)

实例

前段时间朋友发消息来让我帮忙调试一个奇怪的问题,他使用ThinkPHP编写的一个程序,之前用着都好好的,接入微信登录后,便无法正常写入数据,查看ThinkPHP自带的错误信息,提示如下:

ERR: 1364:Field 'avatar' doesn't have a default value
 [ SQL语句 ] : INSERT INTO `xxx_prize` (`user`,`shared`,`time_create`,`get`,`flag`,`type`) VALUES ('1','0','1497445790','0','0','0')

代码里面却是有传入这些参数:

$prize['avatar'] = session('user.headimgurl');
$prize['name'] = 'e';
$prize['prize_name'] = $jackpot[$prizeid]['name'];
$result = $db_prize->add($prize);

因为整体逻辑比较复杂,我之前也没有查看过他的程序,所以我决定用xdebug调试。在这个Controller开头加入调试开关后,刷新页面,就找到了跟踪日志。接下来进行分析。

跟踪日志一共有7000多行,一行一行看肯定是不切实际的。因此,先想办法定位。直接搜索我的用户名,发现是有出现的,因此在取用户名这一段是没有问题的。继续跟踪,来到大约3440行处

用户名

继续往下走,到这里就发现有点不对了,为什么少了几个传入的参数?

少参数

目前已经大概确定了问题发生的范围,接下来查看中间的记录,发现缺少的参数,in_array返回的结果都是FALSE。众所周知,in_array经常被我们拿来检查参数等作用,in_array结果为FALSE本来就有些可疑了。我们通过其他参数进一步确认

in_array

其他参数

基本上确定是被ThinkPHP的某种机制给过滤掉了。接下来,我们打开日志中所写的Model.class.php,找到此处:

Model

大概意思是检查列名是否合法。那么,这个列名又从何而来?我们直接在文件中搜索field,找到关键的两个方法:_checkTableInfoflush。这个函数很明显会有一个缓存的开关,如果有缓存的话,将会从文件中读取列名。

缓存代码

打开缓存文件,发现确实少了几个列名,看来我的猜测基本上是正确的。

缓存

将缓存文件删除后,程序恢复正常。

问题是解决了。那么,为什么之前没有这种情况?询问之下才知道,之前调试模式一直是打开状态,因此,ThinkPHP就不会缓存数据表结构。所以此问题便没有出现。后来关闭了调试模式,但是目录权限没有配置好,就导致了缓存无法写入(此处是猜测)

总结

使用xdebug手动调试程序的话,大概有几个步骤:

1.在代码合适的地方打开调试(xdebug_start_trace)

2.通过数据缩小范围

3.结合代码排查问题

(嗯……好久没有更新博客,都快长草了)