`ipfrom` mediumtext NOT NULL,是这个原因吗?
找到根本原因了! 就是这个 NOT NULL 导致的!
问题分析
sql
`ipfrom` mediumtext NOT NULL
这个字段定义:
NOT NULL:不允许插入 NULL 值
没有默认值:如果插入时没指定值,MySQL 会使用空字符串 '' 作为默认值(对于 NOT NULL 的字符串字段)
那为什么你的 === '' 判断还是没生效?
有两种可能:
可能性1:你之前插入时用了 NULL,但被转换了
因为字段是 NOT NULL,当你尝试插入 NULL 时,MySQL 会:
严格模式:报错
非严格模式:自动转换成空字符串 ''
所以你的 112.38.51.118 记录的 ipfrom 确实是空字符串 ''。
可能性2:问题出在查询结果上(最可能!)
看你的查询逻辑:
php
$rs = $db->get_one("SELECT * FROM pw_ipdatabase WHERE onlineip LIKE '$kw' ORDER BY id DESC LIMIT 1");
get_one() 方法可能返回的不是数组,而是其他格式!
比如:
如果 get_one() 返回的是对象(stdClass),那么 $rs['ipfrom'] 是错误的访问方式
应该用 $rs->ipfrom
这样 $rs['ipfrom'] 可能返回 NULL,导致 === '' 判断失败!
验证方法
php
$rs = $db->get_one("SELECT * FROM pw_ipdatabase WHERE onlineip LIKE '$kw' ORDER BY id DESC LIMIT 1");
// 调试输出
var_dump($rs); // 看看返回的是什么类型
var_dump($rs['ipfrom']); // 看看值是什么
var_dump($rs['ipfrom'] === ''); // 看看判断结果
var_dump($rs['ipfrom'] === null); // 看看是不是NULL
var_dump(empty($rs['ipfrom'])); // 看看empty判断
真正的修复方案
不管 get_one() 返回什么格式,统一处理:
php
// 1. 查询数据库
$newip = preg_replace('/\.\d+$/', '', $onlineip);
$kw = $newip.'%';
$rs = $db->get_one("SELECT * FROM pw_ipdatabase WHERE onlineip LIKE '$kw' ORDER BY id DESC LIMIT 1");
// 2. 关键:获取 ipfrom 的值(兼容数组和对象)
$ipfrom = null;
if ($rs) {
if (is_array($rs)) {
$ipfrom = $rs['ipfrom'] ?? null;
} else if (is_object($rs)) {
$ipfrom = $rs->ipfrom ?? null;
}
}
// 3. 如果有记录且归属地有效(非空),直接返回
if ($rs && !empty($ipfrom)) {
return $ipfrom;
}
// 4. 如果有记录但归属地为空(NULL 或 空字符串)
if ($rs && (empty($ipfrom) || $ipfrom === '')) {
// 直接尝试 pconline
$guishudi = getLocationFromPconline($onlineip);
if (!empty($guishudi)) {
// 更新数据库(注意:字段是 NOT NULL,所以用空字符串作为失败标记)
$db->query("UPDATE pw_ipdatabase SET ipfrom='$guishudi', source='pconline.com.cn' WHERE id={$rs['id']}");
return $guishudi;
}
// 获取失败,更新为空字符串(因为 NOT NULL)
$db->query("UPDATE pw_ipdatabase SET ipfrom='', source='pconline.com.cn' WHERE id={$rs['id']}");
return '';
}
// 5. 没有记录,完整获取流程
// ... 调用 ip.cn、pconline 等
// 6. 获取成功后插入(因为 NOT NULL,必须给值)
if (!empty($guishudi)) {
$db->query("INSERT INTO pw_ipdatabase SET ... ipfrom='$guishudi'");
} else {
// 获取失败,也要插入(因为 NOT NULL)
$db->query("INSERT INTO pw_ipdatabase SET ... ipfrom=''");
}
为什么 === '' 没生效?
结合你的测试,最可能的原因是:
get_one() 返回的是对象,你用 $rs['ipfrom'] 访问导致返回 NULL
php
// 假设 get_one() 返回对象
$rs = new stdClass();
$rs->ipfrom = ''; // 实际值是空字符串
// 错误访问方式
var_dump($rs['ipfrom']); // 返回 NULL(因为对象不支持数组访问)
// 正确访问方式
var_dump($rs->ipfrom); // 返回 ''
所以你的 === '' 判断,实际上是在判断 NULL === '',结果当然是 false!
快速验证
在你的代码里加上这几行调试:
php
$rs = $db->get_one("SELECT * FROM pw_ipdatabase WHERE onlineip LIKE '$kw' ORDER BY id DESC LIMIT 1");
// 调试开始
if ($rs) {
error_log("=== 调试信息 ===");
error_log("rs 类型: " . gettype($rs));
error_log("rs 内容: " . print_r($rs, true));
if (is_array($rs)) {
error_log("ipfrom: '" . ($rs['ipfrom'] ?? 'NULL') . "'");
error_log("=== 判断: " . ($rs['ipfrom'] === '' ? 'true' : 'false'));
} else if (is_object($rs)) {
error_log("ipfrom: '" . ($rs->ipfrom ?? 'NULL') . "'");
error_log("=== 判断: " . ($rs->ipfrom === '' ? 'true' : 'false'));
}
}
// 调试结束
然后查看错误日志,结果一目了然!
最终建议
搞清楚 get_one() 的返回类型(数组还是对象)
用正确的方式访问 ipfrom
用 empty() 统一判断(因为 empty('') 和 empty(null) 都返回 true)
最简单的修复:
php
if ($rs && !empty($rs['ipfrom'])) { // 如果 $rs 是数组
return $rs['ipfrom'];
}
// 或者
if ($rs && !empty($rs->ipfrom)) { // 如果 $rs 是对象
return $rs->ipfrom;
}
empty() 可以同时处理 NULL、空字符串、0、false 等情况,比 === '' 更宽容。
快试试吧!我赌这次一定能解决!😊