Typecho升级到1.3.0后主题搜索报错的解决方法

2026-03-22 38 0

问题原因

Typecho 1.3.0 对 PHP 类型校验更严格了,1.2.1 能兼容 null 传递给需要字符串的函数,1.3.0 会直接抛出 TypeError(类型错误),所以说这就是为什么有些主题在1.2.1可以使用,而1.3.0会直接报错。

解决思路

所以下一步就需要判断是哪个函数报错,首先开启Typecho的debug模式。在根目录的config.inc.php文件中,增加:

/** 开启调试模式 */
define('__TYPECHO_DEBUG__', true);

以我现在使用的Typecho IceFox主题为例:

  • 通过报错溯源到主题 icefoxfunctions.php 第 675 行调用了 $this->permalink
  • 搜索无结果时,Contents.php 里的 path() 方法返回 null,传给 Router::url() 就会报错
  • Typecho 1.3.0 对 PHP 类型校验更严格,1.2.1 能兼容的 null 参数,1.3.0 直接抛出 TypeError

通过报错定位到具体函数 seoInfo() ,找到包含 $this->permalink 的代码段,给$archive->permalink 做空值兜底,例如:

// 原代码(类似这样)
function seoInfo() {
    // ... 其他代码 ...
    $permalink = $this->permalink; // 第675行左右
    // ... 其他代码 ...
}

// 修改后的代码(增加空值判断)
function seoInfo() {
    if ($archive->is('search') && $archive->total == 0) {
    // 搜索无结果时,强制把permalink设为网站首页地址
    $permalink = $options->siteUrl;
    } else {
    // 其他情况:有值就用原值,无值就兜底为首页
    $permalink = $archive->permalink ?? $options->siteUrl;
    }
    // ... 其他代码保持不变 ...
}

我使用的主题搜索无结果时,$archive->permalink 返回 null,传给 htmlspecialchars() 后再传给 Router::url(),触发类型错误,所以还需要处理htmlspecialchars。处理完成后完整的seoInfo()函数代码:

/**
 * 输出SEO信息
 */
function seoInfo($archive)
{
    $options = Helper::options();

    if ($archive->is('index')) {
        $title = $options->title;
        $description = $options->description;
        $keywords = $options->keywords;
    } elseif ($archive->is('post') || $archive->is('page')) {
        $title = $archive->title . ' - ' . $options->title;
        // 清理文章摘要:移除HTML标签、换行符,并截取前150个字符
        $description = strip_tags($archive->excerpt);
        $description = preg_replace('/\s+/', ' ', $description); // 将多个空白字符替换为单个空格
        $description = trim($description);
        $description = mb_substr($description, 0, 150, 'UTF-8');
        $keywords = '';
        if ($archive->tags) {
            foreach ($archive->tags as $tag) {
                $keywords .= $tag['name'] . ',';
            }
        }
        $keywords = rtrim($keywords, ',');
    } else {
        // 归档页面:根据不同类型生成标题
        $archiveTitle = '';
        if ($archive->is('category')) {
            $archiveTitle = '分类 ' . $archive->getDescription() . ' 下的文章';
        } elseif ($archive->is('tag')) {
            $archiveTitle = '标签 ' . $archive->getDescription() . ' 下的文章';
        } elseif ($archive->is('author')) {
            $archiveTitle = $archive->getDescription() . ' 发布的文章';
        } elseif ($archive->is('search')) {
            // 尝试多种方式获取搜索关键词
            $searchKeywords = '';
            
            // 调试:检查所有可能的搜索参数来源
            $request = $archive->request;
            
            if ($request) {
                $searchKeywords = $request->get('keywords', '');
                if (empty($searchKeywords)) {
                    $searchKeywords = $request->get('s', '');
                }
            }
            
            // 如果还是空,尝试从$_GET获取
            if (empty($searchKeywords) && isset($_GET['keywords'])) {
                $searchKeywords = $_GET['keywords'];
            }
            if (empty($searchKeywords) && isset($_GET['s'])) {
                $searchKeywords = $_GET['s'];
            }
            
            $archiveTitle = '包含关键字 ' . $searchKeywords . ' 的文章';
        } else {
            // 使用默认归档标题
            $archiveTitle = '归档';
        }
        
        $title = $archiveTitle . ' - ' . $options->title;
        $description = $options->description;
        $keywords = $options->keywords;
    }
    
     // 搜索无结果时,permalink指向首页;其他情况用原permalink(无值则兜底首页)
    if ($archive->is('search') && $archive->total == 0) {
        $permalink = $options->siteUrl;
    } else {
        $permalink = $archive->permalink ?? $options->siteUrl;
    }

    // 转义所有输出内容,防止HTML注入
    $title = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
    $description = htmlspecialchars($description, ENT_QUOTES, 'UTF-8');
    $keywords = htmlspecialchars($keywords, ENT_QUOTES, 'UTF-8');
    $permalink = htmlspecialchars($permalink, ENT_QUOTES, 'UTF-8'); // 转义permalink

    echo '<title>' . $title . '</title>' . "\n";
    echo '    <meta name="description" content="' . $description . '">' . "\n";
    echo '    <meta name="keywords" content="' . $keywords . '">' . "\n";

    // Open Graph
    echo '    <meta property="og:title" content="' . $title . '">' . "\n";
    echo '    <meta property="og:description" content="' . $description . '">' . "\n";
    echo '    <meta property="og:type" content="website">' . "\n";
    echo '    <meta property="og:url" content="' . $permalink . '">' . "\n"; // 替换原$archive->permalink
    echo '    <meta property="og:site_name" content="' . htmlspecialchars($options->title, ENT_QUOTES, 'UTF-8') . '">' . "\n";

    // Twitter Card
    echo '    <meta name="twitter:card" content="summary">' . "\n";
    echo '    <meta name="twitter:title" content="' . $title . '">' . "\n";
    echo '    <meta name="twitter:description" content="' . $description . '">';
}

相关文章

Typecho1.2.1 XSS漏洞
UptimeRobot网站监控调用方法
虚拟主机WordPress部署SSL注意事项(301跳转)
中兴问天BE7200Pro+路由器外网访问设置
电信宽带更换中兴G7615光猫
荣耀magic5系列手机禁用系统更新

发布评论