这天正在写文章,写完了发布后准备看下,博客主页突然提示 Unsupported operand types: int - string 主页都打不开了
排查问题
"Unsupported operand types: int - string"
是 PHP 8.x 开始变得更严格之后常见的 类型错误。
✅ 意思解释:
代码里某个地方 试图用整数(int)减去一个字符串(string),比如:
$count = 10 - "3"; // 在 PHP 7 里会自动转换,PHP 8 会报错
✅ 为什么突然报错?
最近可能:
- 升级了 PHP 版本(比如从 7.x 升到 8.x)
- 安装了新插件或主题
- 修改了某些代码
✅ 怎么定位问题?
方法一:看完整错误信息
Typecho 默认可能只显示一行错误,可以打开 debug 模式,看到完整堆栈:
- 打开
config.inc.php
- 加一行:
define('__TYPECHO_DEBUG__', true);
- 刷新页面,会看到 文件名 + 行号,比如:
Fatal error: Uncaught TypeError: Unsupported operand types: int - string in /var/www/var/Widget/Archive.php:123
方法二:查插件或主题
- 如果最近装了 新插件 或 换了主题,先禁用它们,看错误是否消失。
- 特别是 评论数、浏览数、点赞数 这类地方,最容易出现
int - string
的操作。
✅ 举个例子(真实案例):
某用户用了个老插件,代码里写了:
$comments = $db->fetchRow($sql)['count'] - $post->commentsNum;
结果 $post->commentsNum
是字符串 "0"
,PHP 8 就报错了。
✅ 快速修复(临时):
改代码,把字符串强制转成整数:
$comments = $db->fetchRow($sql)['count'] - (int)$post->commentsNum;
✅ 总结一句话:
某个插件或主题的代码,在 PHP 8 下试图用整数减字符串,导致报错。
可问题是博客已经很久很久没改过啥东西了,既没新插件,也没动过主题代码,加上调试代码后日志显示之前做美化的一段个性化代码的问题。这段博客右侧的统计代码,已经忘记是从哪里抄来的了 🌚 统计在线人数的时候,会在博客主目录下生成一个 $filename = 'online.txt'; // 数据文件
美化代码
<?php
// 在线人数
function online_users() {
$filename = 'online.txt'; // 数据文件
$cookiename = 'Nanlon_OnLineCount'; // Cookie 名称
$onlinetime = 30; // 在线有效时间
$online = file($filename);
$nowtime = $_SERVER['REQUEST_TIME'];
$nowonline = array();
foreach ($online as $line) {
$row = explode('|', $line);
$sesstime = trim($row[1]);
if (($nowtime - $sesstime) <= $onlinetime) {
$nowonline[$row[0]] = $sesstime;
}
}
if (isset($_COOKIE[$cookiename])) {
$uid = $_COOKIE[$cookiename];
} else {
$vid = 0;
do {
$vid++;
$uid = 'U' . $vid;
} while (array_key_exists($uid, $nowonline));
setcookie($cookiename, $uid);
}
$nowonline[$uid] = $nowtime;
$total_online = count($nowonline);
if ($fp = @fopen($filename, 'w')) {
if (flock($fp, LOCK_EX)) {
rewind($fp);
foreach ($nowonline as $fuid => $ftime) {
$fline = $fuid . '|' . $ftime . "\n";
@fputs($fp, $fline);
}
flock($fp, LOCK_UN);
fclose($fp);
}
}
echo "$total_online";
}
// 字数统计
function allOfCharacters() {
$chars = 0;
$db = Typecho_Db::get();
$select = $db->select('text')->from('table.contents');
$rows = $db->fetchAll($select);
foreach ($rows as $row) {
$chars += mb_strlen(trim($row['text']), 'UTF-8');
}
$unit = '';
if ($chars >= 10000) {
$chars /= 10000;
$unit = '万';
} else if ($chars >= 1000) {
$chars /= 1000;
$unit = '千';
}
$out = sprintf('%.2lf %s', $chars, $unit);
return $out;
}
// 总访问量
function theAllViews(){
$db = Typecho_Db::get();
$row = $db->fetchAll('SELECT SUM(VIEWS) FROM `typecho_contents`');
echo number_format($row[0]['SUM(VIEWS)']);
}
// 响应时间
function timer_start() {
global $timestart;
$mtime = explode(' ', microtime());
$timestart = $mtime[1] + $mtime[0];
return true;
}
timer_start();
function timer_stop($display = 0, $precision = 3) {
global $timestart, $timeend;
$mtime = explode(' ', microtime());
$timeend = $mtime[1] + $mtime[0];
$timetotal = number_format($timeend - $timestart, $precision);
$r = $timetotal < 1 ? $timetotal * 1000 . " ms" : $timetotal . " s";
if ($display) {
echo $r;
}
return $r;
}
online.txt 的记录格式
U1|1760161677
U10|1760161676
U1|1760161678
U12|1760161676
U13|1760161676
U14|1760161676
U15|1760161676
U16|1760161676
U17|1760161677
U18|1760161676
U19|1760161676
U20|1760161677
U21|1760161676
U22|1760161677
U23|1760161676
U24|1760161677
U25|1760161676
U26|1760161677
U27|1760161677
U28|1760161677
U29|1760161677
U30|1760161677
U31|1760161677
U32|1760161677
U33|1760161677
U34|1760161677
U35|1760161677
U36|1760161677
U37|1760161677
U38|1760161677
U39|1760161677
U40|1760161677
U41|1760161677
U42|1760161677
U43|1760161677
U44|1760161677
U45|1760161677
U46|1760161677
U47|1760161677
U48|1760161677
U49|1760161677
U50|1760161677
U51|1760161677
U52|1760161677
U53|1760161677
U54|1760161677
U55|1760161677
U56|1760161677
U57|1760161677
处理问题
这段代码本身 没有直接出现 int - string
,但它非常接近出错边缘,而且在 PHP 8 下确实会触发那个错误:
🔥 问题出在这行:
$sesstime = trim($row[1]);
然后:
if (($nowtime - $sesstime) <= $onlinetime) {
✅ 原因:
$row[1]
是字符串,比如"1760161677"
trim()
之后还是 字符串- PHP 8 不允许直接用
int - string
,会报错:
Unsupported operand types: int - string
✅ 修复方法:
把 $sesstime
强制转成 int:
$sesstime = (int)trim($row[1]);
✅ 改完后的完整片段:
foreach ($online as $line) {
$row = explode('|', $line);
if (count($row) < 2) continue; // 防止空行或格式错误
$sesstime = (int)trim($row[1]); // ✅ 强制转 int
if (($nowtime - $sesstime) <= $onlinetime) {
$nowonline[$row[0]] = $sesstime;
}
}
✅ 建议再补一个容错:
如果 online.txt
有空行或格式不对,explode
可能得不到 [1]
,会出 Undefined offset,所以建议加:
if (count($row) < 2) continue;
✅ 总结一句话:
把$sesstime
强制转成(int)
,就能彻底解决这个 PHP 8 报错。
此处评论已关闭