functions.php 公共复用函数

将以下代码粘贴到主题根目录 functions.php 最底部,不要覆盖原有函数:

<?php
/**
 * 浏展网公共展会工具函数 方案B模块化通用
 * 首页/详情/筛选页统一调用,一处修改全站生效
 */

if (!defined('ABSPATH')) exit;

/**
 * 1. 获取随机默认展会封面图(统一图片数组,消除3处重复)
 * @return string 完整图片URL
 */
function get_random_expo_default_img() {
    static $expo_images = [
        '10-400x300.jpg','20-400x300.jpg','26-400x300.jpg','30-400x300.jpg','34-400x300.jpg',
        '38-400x300.jpg','42-400x300.jpg','43-400x300.jpg','48-400x300.jpg','54-400x300.jpg',
        '58-400x300.jpg','62-400x300.jpg','65-400x300.jpg','72-400x300.jpg','78-400x300.jpg',
        '82-400x300.jpg','84-400x300.jpg','88-400x300.jpg','91-400x300.jpg','96-400x300.jpg',
        '103-400x300.jpg','106-400x300.jpg','110-400x300.jpg','119-400x300.jpg','123-400x300.jpg',
        '131-400x300.jpg','139-400x300.jpg','142-400x300.jpg','149-400x300.jpg','155-400x300.jpg',
        '164-400x300.jpg','171-400x300.jpg','179-400x300.jpg','186-400x300.jpg','192-400x300.jpg',
        '198-400x300.jpg','212-400x300.jpg','218-400x300.jpg','242-400x300.jpg','258-400x300.jpg',
    ];
    shuffle($expo_images);
    $img = reset($expo_images);
    return get_template_directory_uri() . '/images/default-expo/' . $img;
}

/**
 * 2. 统一获取展会状态文字(倒计时/开展中/已结束)
 * @param string $start 展会开始日期 Y-m-d
 * @param string $end 展会结束日期 Y-m-d
 * @return string 状态文案
 */
function get_expo_status_text(string $start = '', string $end = ''): string {
    if (empty($start) && empty($end)) {
        return '未填写';
    }
    $today_ts = strtotime(date('Y-m-d'));
    $start_ts = strtotime($start);
    $end_ts = strtotime($end);

    if ($today_ts < $start_ts) {
        $diff_days = ceil(($start_ts - $today_ts) / 86400);
        return "距离开展 {$diff_days} 天";
    } elseif ($today_ts >= $start_ts && $today_ts <= $end_ts) {
        return '开展中';
    } else {
        return '已结束';
    }
}

/**
 * 3. 统一阅读量兼容函数(整合expo_read / post_views_count两套字段)
 * @param int $post_id 文章ID
 * @return string 阅读数字符串
 */
function getPostViews(int $post_id): string {
    $views = get_post_meta($post_id, 'post_views_count', true);
    if (empty($views)) {
        $views = get_post_meta($post_id, 'expo_read', true);
    }
    return empty($views) ? '0' : esc_html($views);
}

/**
 * 4. 安全获取展会自定义字段(自动转义,解决XSS漏洞)
 * @param int $pid 文章ID
 * @param string $meta_key 字段名
 * @param string $default 默认值
 * @return string 转义后文本
 */
function get_expo_meta(int $pid, string $meta_key, string $default = '暂未公布'): string {
    $val = get_post_meta($pid, $meta_key, true);
    return empty($val) ? esc_html($default) : esc_html($val);
}

/**
 * 5. 展会日期格式化输出
 * @param string $start 开始时间
 * @param string $end 结束时间
 * @return string 标准化日期文本
 */
function get_expo_date_range(string $start = '', string $end = ''): string {
    if (empty($start)) return '未填写';
    $s = date('Y-m-d', strtotime($start));
    if (!empty($end)) {
        $e = date('Y-m-d', strtotime($end));
        return "{$s} ~ {$e}";
    }
    return $s;
}

/**
 * 6. 统计文章阅读量(统一计数入口)
 */
function set_post_view_count() {
    if (is_single()) {
        global $post;
        $pid = $post->ID;
        $current = get_post_meta($pid, 'post_views_count', true) ?: 0;
        update_post_meta($pid, 'post_views_count', (int)$current + 1);
    }
}
add_action('wp_head', 'set_post_view_count');

使用说明(方案 B 改造模板简化写法)

  1. 随机默认图: 旧重复数组全部删除,替换为:<?php $img_url = get_random_expo_default_img(); ?>
  2. 展会状态文字: 删除页面内大量日期判断代码,替换:<?php echo get_expo_status_text($start_time, $end_time); ?>
  3. 自定义字段输出: <?php echo get_expo_meta($pid, 'Exhibition_City'); ?> 自动转义,不用重复写esc_html()
  4. 展会日期区间: <?php echo get_expo_date_range($start, $end); ?>
  5. 阅读量统一: <?php echo getPostViews(get_the_ID()); ?>

三、模块化拆分文件清单(长期维护推荐新建)

在主题 inc/ 文件夹新建以下复用模板,三张页面统一引入,彻底消除重复 HTML:

  1. inc/expo-card-item.php —— 展会列表卡片(首页 / 筛选页共用)
  2. inc/sidebar-expo.php —— 侧边栏通用模块(详情页 / 首页共用)
  3. inc/expo-meta-info.php —— 详情页顶部展会基础信息块
  4. inc/expo-default-img.php —— 默认图渲染片段
  5. inc/pagination-expo.php —— 统一分页组件
  6. inc/ad-widget.php —— 广告位通用模板

使用教程

小白专用完整示例,分两种场景:筛选列表卡片、详情页头部

先记住规则

  1. 所有函数已经放进 functions.php,直接复制粘贴用,不用改数组、不用手动转义
  2. $pid = 当前文章 ID,列表页用 get_the_ID(),详情页顶部已经定义好 $pid

示例 1:筛选页 / 首页 展会卡片(列表循环里直接套)

把你原来一大段随机图片、日期判断全部删掉,替换成下面整套:

<?php
// 1. 获取随机默认图地址
$img_url = get_random_expo_default_img();
// 2. 获取当前展会起止时间字段
$start_time = get_post_meta(get_the_ID(), 'Exhibition_start_time', true);
$end_time   = get_post_meta(get_the_ID(), 'Exhibition_end_time', true);
// 3. 展会城市
$city = get_expo_meta(get_the_ID(), 'Exhibition_City');
// 4. 完整展会日期区间
$date_text = get_expo_date_range($start_time, $end_time);
// 5. 展会状态:距离开展X天 / 开展中 / 已结束
$status_text = get_expo_status_text($start_time, $end_time);
// 6. 阅读次数
$view_num = getPostViews(get_the_ID());
?>

<!-- 图片区域 -->
<div class="post-thumbnail">
    <?php if (has_post_thumbnail()) : ?>
        <a href="<?php the_permalink(); ?>">
            <?php the_post_thumbnail('medium_large', ['loading' => 'lazy']); ?>
        </a>
    <?php else : ?>
        <a href="<?php the_permalink(); ?>">
            <img src="<?php echo esc_url($img_url); ?>" alt="<?php the_title_attribute(); ?>" loading="lazy">
        </a>
    <?php endif; ?>

    <!-- 右下角状态角标 -->
    <div class="exhibition-time-badge">
        <?php echo $status_text; ?>
    </div>
</div>

<!-- 卡片文字信息 -->
<div class="post-card-content">
    <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    <div class="post-meta">
        <span>📍 举办城市:<?php echo $city; ?></span>
        <span>🗓️ 展会时间:<?php echo $date_text; ?></span>
        <span>👁️ 浏览:<?php echo $view_num; ?>次</span>
    </div>
    <a href="<?php the_permalink(); ?>" class="read-more">查看详情 →</a>
</div>

示例 2:详情页 single.php 头部信息块(页面顶部已有 $pid 变量,直接用)

<?php
// 读取字段
$startDate = get_post_meta($pid, 'Exhibition_start_time', true);
$endDate   = get_post_meta($pid, 'Exhibition_end_time', true);
// 调用公共函数
$status_text = get_expo_status_text($startDate, $endDate);
$city        = get_expo_meta($pid, 'Exhibition_City');
$venue       = get_expo_meta($pid, 'Exhibition_venues');
$date_range  = get_expo_date_range($startDate, $endDate);
$views       = getPostViews($pid);
?>

<!-- 展会信息行 -->
<li>
    <strong>展会状态:</strong>
    <span style="color:red"><?php echo $status_text; ?></span>
</li>
<li>
    <strong>举办城市:</strong><?php echo $city; ?> - <?php echo $venue; ?>
</li>
<li>
    <strong>完整展期:</strong><?php echo $date_range; ?>
</li>
<li>
    <strong>浏览次数:</strong><?php echo $views; ?> 次
</li>

每个函数单独拆解解释(看懂就会灵活套用)

  1. $img_url = get_random_expo_default_img(); 自动从 40 张默认图里随机返回一张完整网址,不需要写长长的图片数组。 输出图片时必须套 echo esc_url($img_url) 保证安全。
  2. get_expo_status_text($start_time, $end_time) 只需要传入展会开始、结束日期,自动输出:距离开展XX天 / 开展中 / 已结束 / 未填写,不用自己写一堆 if 判断。
  3. get_expo_meta($id, '自定义字段名', '默认文字') 自动读取自定义字段,自带 esc_html 防攻击; 第三个参数不填默认显示 “暂未公布”,例:get_expo_meta($pid, 'Sponsor', '暂无主办方信息')
  4. get_expo_date_range($start, $end) 自动拼接 2026-05-01 ~ 2026-05-05,没有结束日期只显示开始日,空值显示未填写。
  5. getPostViews(文章ID) 统一读取阅读量,兼容两套阅读字段,没有阅读量自动输出 0。

替换操作步骤

  1. 先把 functions.php 底部粘贴我给你的公共函数代码并保存;
  2. 打开首页 / 筛选 / 详情模板;
  3. 找到原来一大段 static $expo_images 图片数组、一堆日期 if 判断代码,全部删除;
  4. 复制上面对应场景的示例代码粘贴进去;
  5. 刷新页面即可正常显示,无报错。