You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress中实现带参数的PHP排行榜函数,通过短码控制返回的行数与列数

WordPress中实现带参数的PHP排行榜函数,通过短码控制返回的行数与列数

我来帮你一步步实现这个需求,WordPress短码的参数处理有固定套路,咱们可以通过修改现有函数,轻松实现按需返回指定行数和列的功能。直接上修改后的完整代码,之后再拆解关键改动:

function display_singles_ladder($atts) {
    global $wpdb;

    // 1. 处理短码参数,设置默认值
    $args = shortcode_atts(
        array(
            'limit' => null, // 默认返回所有行
            'columns' => 'rank,player,matches_played,wins,losses,games_won,games_lost,win_streak,pending_challenges' // 默认显示所有列
        ),
        $atts,
        'singles_ladder'
    );

    // 定义合法列映射:别名 => [表头文本, 数据键名]
    $allowed_columns = array(
        'rank' => array('label' => 'Rank', 'data_key' => 'player_rank'),
        'player' => array('label' => 'Player', 'data_key' => 'player_name'),
        'matches_played' => array('label' => 'Matches Played', 'data_key' => 'matches_played'),
        'wins' => array('label' => 'Match Wins', 'data_key' => 'wins'),
        'losses' => array('label' => 'Match Losses', 'data_key' => 'losses'),
        'games_won' => array('label' => 'Game Wins', 'data_key' => 'games_won'),
        'games_lost' => array('label' => 'Game Losses', 'data_key' => 'games_lost'),
        'win_streak' => array('label' => 'Win Streak', 'data_key' => 'win_streak'),
        'pending_challenges' => array('label' => 'Challenges', 'data_key' => 'pending_challenges')
    );

    // 过滤用户传入的列,只保留合法列
    $selected_columns = array_intersect(explode(',', strtolower($args['columns'])), array_keys($allowed_columns));
    // 防止用户传全错的列,至少保留核心列
    if (empty($selected_columns)) {
        $selected_columns = array('rank', 'player');
    }

    // 数据库表定义(和原函数一致)
    $ranking_table = $wpdb->prefix . 'player_rankings';
    $players_table = $wpdb->prefix . 'players';
    $match_players_table = $wpdb->prefix . 'match_players';
    $matches_table = $wpdb->prefix . 'matches';
    $results_table = $wpdb->prefix . 'match_results';
    $game_scores_table = $wpdb->prefix . 'match_games';

    // 2. 构建动态SQL查询,添加LIMIT条件
    $sql = "
        SELECT r.player_id, r.player_rank, CONCAT(p.first_name, ' ', p.last_name) AS player_name,
            (
                SELECT COUNT(*) FROM {$wpdb->prefix}challenges c
                WHERE c.challenged_id = p.player_id AND c.match_type_id = 1 AND c.status = 'pending'
            ) AS pending_challenges
        FROM $ranking_table r
        JOIN $players_table p ON r.player_id = p.player_id
        WHERE r.match_type_id = 1
        ORDER BY r.player_rank ASC
    ";

    // 安全添加LIMIT(用prepare防止SQL注入)
    if (isset($args['limit']) && is_numeric($args['limit']) && $args['limit'] > 0) {
        $sql .= $wpdb->prepare(" LIMIT %d ", $args['limit']);
    }

    $players = $wpdb->get_results($sql, ARRAY_A);

    if (empty($players)) {
        return "<p>No ladder data available for singles.</p>";
    }

    ob_start();
    echo "<table class='singles-ladder'>";
    echo "<thead><tr>";

    // 3. 动态生成表头
    foreach ($selected_columns as $col) {
        echo "<th>" . esc_html($allowed_columns[$col]['label']) . "</th>";
    }

    echo "</tr></thead><tbody>";

    foreach ($players as $player) {
        $player_id = (int)$player['player_id'];

        // 原有的比赛/游戏统计查询保持不变
        $match_stats = $wpdb->get_row($wpdb->prepare("
            SELECT COUNT(*) AS matches_played,
                SUM(CASE WHEN mp.team_number = 1 AND r.team1_score > r.team2_score THEN 1
                        WHEN mp.team_number = 2 AND r.team2_score > r.team1_score THEN 1
                        ELSE 0 END) AS wins,
                SUM(CASE WHEN mp.team_number = 1 AND r.team1_score < r.team2_score THEN 1
                        WHEN mp.team_number = 2 AND r.team2_score < r.team1_score THEN 1
                        ELSE 0 END) AS losses
            FROM $match_players_table mp
            JOIN $matches_table m ON mp.match_id = m.match_id
            JOIN $results_table r ON r.match_id = m.match_id
            WHERE mp.player_id = %d AND m.match_type_id = 1
        ", $player_id), ARRAY_A);

        $game_stats = $wpdb->get_row($wpdb->prepare("
            SELECT SUM(CASE WHEN mp.team_number = 1 AND gs.team1_score > gs.team2_score THEN 1
                            WHEN mp.team_number = 2 AND gs.team2_score > gs.team1_score THEN 1
                            ELSE 0 END) AS games_won,
                SUM(CASE WHEN mp.team_number = 1 AND gs.team1_score < gs.team2_score THEN 1
                            WHEN mp.team_number = 2 AND gs.team2_score < gs.team1_score THEN 1
                            ELSE 0 END) AS games_lost
            FROM $match_players_table mp
            JOIN $matches_table m ON mp.match_id = m.match_id
            JOIN $game_scores_table gs ON gs.match_id = m.match_id
            WHERE mp.player_id = %d AND m.match_type_id = 1
        ", $player_id), ARRAY_A);

        $win_streak = get_player_win_streak($player_id);

        // 合并所有数据到一个数组,方便统一调用
        $player_data = array_merge(
            $player,
            $match_stats,
            $game_stats,
            array('win_streak' => $win_streak)
        );

        echo "<tr>";
        // 4. 动态生成表格行内容
        foreach ($selected_columns as $col) {
            $data_key = $allowed_columns[$col]['data_key'];
            $value = $player_data[$data_key] ?? '';

            // 保留原有的特殊样式逻辑
            if ($col === 'player') {
                $value .= $player['player_rank'] == 1 ? ' 👑' : '';
            }
            if ($col === 'pending_challenges') {
                $value = $value > 0 
                    ? "<span style='color: orange;'>⚔️ {$value} pending</span>" 
                    : "<span style='color: gray;'>—</span>";
            }

            echo "<td>" . wp_kses_post($value) . "</td>";
        }
        echo "</tr>";
    }

    echo "</tbody></table>";
    return ob_get_clean();
}

add_shortcode('singles_ladder', 'display_singles_ladder');

关键改动说明

  1. 短码参数标准化处理
    用shortcode_atts()统一管理参数,设置了合理的默认值,同时通过$allowed_columns过滤无效列,避免用户传错参数导致错误。

  2. 安全的SQL LIMIT拼接
    用$wpdb->prepare()处理LIMIT参数,彻底避免SQL注入风险,这是WordPress数据库操作的标准安全规范。

  3. 动态表格渲染
    表头和表格内容都通过循环$selected_columns生成,不用写一堆冗余的判断逻辑,后续新增列只需要在$allowed_columns里加映射即可。

  4. 特殊逻辑的兼容
    保留了原函数中冠军标记、挑战状态样式的特殊处理,确保这些细节在动态列中依然生效。


短码调用示例

现在你可以灵活控制显示内容了:

  • 显示完整排行榜:[singles_ladder]
  • 只显示前5名:[singles_ladder limit="5"]
  • 只显示核心列:[singles_ladder columns="rank,player,wins,losses"]
  • 组合使用:[singles_ladder limit="3" columns="rank,player,win_streak"]

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 12:19:33