php+mysql 搭建一个在线游戏网站目前已有2000+游戏【代码解析 一】

本文将详细介绍如何使用 PHP 和 MySQL 搭建一个功能完善的在线游戏网站,并附上完整的代码。目前,该网站已收录 2000+ 游戏,支持分类筛选、搜索、分页、随机推荐等功能。

在线预览链接1:game.haiyong.site/

预览链接2(新网址):peergame.cn/

项目概述

1. 功能特点

  • 游戏展示:支持按分类、热门、随机等方式展示游戏。
  • 分类筛选:提供多种游戏分类,用户可以根据兴趣筛选游戏。
  • 搜索功能:支持按游戏名称搜索。
  • 分页功能:游戏列表支持分页显示,提升用户体验。
  • 点击统计:记录每个游戏的点击次数,方便统计热门游戏。
  • 响应式设计:适配 PC 和移动端,提供良好的浏览体验。

2. 技术栈

  • 前端:HTML、CSS、Bootstrap、JavaScript
  • 后端:PHP
  • 数据库:MySQL

@TOC

一、数据库设计与连接

1. 表结构

数据库包含以下表:

1.1 games

存储游戏的基本信息。

字段名 类型 说明
id INT 游戏 ID
name VARCHAR(255) 游戏名称
description TEXT 游戏描述
game_url VARCHAR(255) 游戏链接
image_url VARCHAR(255) 游戏封面图链接
clicks INT 点击次数

1.2 categories

存储游戏分类信息。

字段名 类型 说明
id INT 分类 ID
category_name VARCHAR(255) 分类名称

1.3 game_category

存储游戏与分类的关联关系。

字段名 类型 说明
game_id INT 游戏 ID
category_id INT 分类 ID

2.使用 PDO 连接 MySQL

PHP 的 PDO(PHP Data Objects)是一个轻量级的数据库访问抽象层,支持多种数据库(如 MySQL、PostgreSQL 等)。以下是连接 MySQL 的代码:

php 复制代码
<?php
// 数据库连接配置
$host = "localhost";          // 数据库地址
$dbname = "your_database";   // 数据库名称
$username = "your_username"; // 数据库用户名
$password = "your_password"; // 数据库密码

try {
    // 创建 PDO 实例
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
    // 设置错误模式为异常模式
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    // 捕获异常并输出错误信息
    die("数据库连接失败: " . $e->getMessage());
}
?>

关键点

  • PDO:PHP 的数据库访问抽象层,支持多种数据库。
  • ATTR_ERRMODE :设置错误处理模式,ERRMODE_EXCEPTION 表示抛出异常。
  • try-catch:捕获数据库连接异常,避免直接暴露错误信息。

二、数据处理

以下是对这段代码的详细展开说明,涵盖分类筛选、搜索、分页、排序等功能的实现逻辑。


2.1.处理分类和搜索

2.1.1 获取分类和搜索条件

php 复制代码
$category_filter = isset($_GET['category']) ? trim($_GET['category']) : '';
$searchQuery = isset($_GET['search']) ? trim($_GET['search']) : '';

功能:

  • 从 URL 参数中获取用户选择的分类(category)和搜索关键词(search)。
  • 使用 trim() 函数去除多余的空格。

示例:

  • 如果用户访问 ?category=动作&search=冒险,则:
    • $category_filter = "动作"
    • $searchQuery = "冒险"

2.1.2 分页设置

php 复制代码
$gamesPerPage = 20; // 每页显示的游戏数量
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1; // 当前页码
$offset = ($page - 1) * $gamesPerPage; // 计算偏移量

功能:

  • 设置每页显示的游戏数量($gamesPerPage)。
  • 从 URL 参数中获取当前页码(page),默认为第 1 页。
  • 计算数据库查询的偏移量($offset),用于分页。

示例:

  • 如果用户访问 ?page=3,则:
    • $page = 3
    • $offset = (3 - 1) * 20 = 40,表示从第 41 条记录开始查询。

2.2 获取总游戏数

2.2.1 动态生成 SQL 查询

php 复制代码
$query = "SELECT COUNT(*) FROM (
            SELECT g.id 
            FROM games g
            LEFT JOIN game_category gc ON g.id = gc.game_id
            LEFT JOIN categories c ON gc.category_id = c.id
            WHERE 1=1";

if ($category_filter && $category_filter !== '热门') {
    $query .= " AND c.category_name = :category";
}
if ($searchQuery) {
    $query .= " AND g.name LIKE :search";
}

$query .= " GROUP BY g.id
          ) AS subquery";

功能:

  • 动态生成 SQL 查询,统计符合条件的游戏总数。
  • 如果用户选择了分类(且分类不是"热门"),则添加分类筛选条件。
  • 如果用户输入了搜索关键词,则添加搜索条件。
  • 使用 GROUP BY g.id 去重,避免重复统计。

示例:

  • 如果用户选择分类为"动作"并搜索"冒险",则生成的 SQL 为:

    sql 复制代码
    SELECT COUNT(*) FROM (
        SELECT g.id 
        FROM games g
        LEFT JOIN game_category gc ON g.id = gc.game_id
        LEFT JOIN categories c ON gc.category_id = c.id
        WHERE 1=1
        AND c.category_name = '动作'
        AND g.name LIKE '%冒险%'
        GROUP BY g.id
    ) AS subquery

2.2.2 执行查询并获取总游戏数

php 复制代码
$stmt = $pdo->prepare($query);
if ($category_filter && $category_filter !== '热门') {
    $stmt->bindValue(':category', $category_filter, PDO::PARAM_STR);
}
if ($searchQuery) {
    $stmt->bindValue(':search', "%$searchQuery%", PDO::PARAM_STR);
}
$stmt->execute();
$totalGames = $stmt->fetchColumn();
$totalPages = ceil($totalGames / $gamesPerPage);

功能:

  • 使用 PDO 预处理语句执行查询,防止 SQL 注入。
  • 绑定分类和搜索参数。
  • 获取符合条件的游戏总数($totalGames)。
  • 计算总页数($totalPages),用于分页显示。

示例:

  • 如果总游戏数为 100,每页显示 20 个游戏,则:
    • $totalPages = ceil(100 / 20) = 5

3.1 获取游戏数据

3.1.1 热门游戏逻辑

php 复制代码
if ($category_filter === '热门') {
    // 热门游戏按点击次数排序
    $all_games_query = "SELECT g.*, g.clicks FROM games g
                        LEFT JOIN game_category gc ON g.id = gc.game_id
                        LEFT JOIN categories c ON gc.category_id = c.id
                        WHERE 1=1";

    if ($searchQuery) {
        $all_games_query .= " AND g.name LIKE :search";
    }

    $all_games_query .= " GROUP BY g.id";

    $all_games_stmt = $pdo->prepare($all_games_query);
    if ($searchQuery) {
        $all_games_stmt->bindValue(':search', "%$searchQuery%", PDO::PARAM_STR);
    }
    $all_games_stmt->execute();
    $all_games = $all_games_stmt->fetchAll(PDO::FETCH_ASSOC);

    // 按访问次数排序
    usort($all_games, function ($a, $b) {
        return $b['clicks'] - $a['clicks'];
    });

    // 分页处理
    $games = array_slice($all_games, $offset, $gamesPerPage);
}

功能:

  • 如果用户选择"热门"分类,则按点击次数(clicks)从高到低排序。
  • 支持搜索功能。
  • 使用 array_slice 实现分页。

示例:

  • 如果用户选择"热门"分类并搜索"冒险",则:
    • 查询所有符合条件的游戏。
    • 按点击次数排序。
    • 根据当前页码和每页数量,截取对应的游戏数据。

3.1.2 其他分类逻辑

php 复制代码
else {
    // 其他分类的逻辑
    $query = "SELECT g.*, g.clicks FROM games g
              LEFT JOIN game_category gc ON g.id = gc.game_id
              LEFT JOIN categories c ON gc.category_id = c.id
              WHERE 1=1";

    if ($category_filter) {
        $query .= " AND c.category_name = :category";
    }
    if ($searchQuery) {
        $query .= " AND g.name LIKE :search";
    }

    $query .= " GROUP BY g.id";

    // 随机排序
    if (empty($category_filter) || ($category_filter && $category_filter !== '热门')) {
        $query .= " ORDER BY RAND(:seed)";
    } else {
        $query .= " ORDER BY g.id ASC";
    }

    $query .= " LIMIT :offset, :limit";

    $stmt = $pdo->prepare($query);
    if ($category_filter) {
        $stmt->bindValue(':category', $category_filter, PDO::PARAM_STR);
    }
    if ($searchQuery) {
        $stmt->bindValue(':search', "%$searchQuery%", PDO::PARAM_STR);
    }
    if (empty($category_filter) || ($category_filter && $category_filter !== '热门')) {
        $stmt->bindValue(':seed', $seed, PDO::PARAM_INT);
    }
    $stmt->bindValue(":offset", $offset, PDO::PARAM_INT);
    $stmt->bindValue(":limit", $gamesPerPage, PDO::PARAM_INT);

    $stmt->execute();
    $games = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

功能:

  • 如果用户选择其他分类,则按分类筛选游戏。
  • 支持搜索功能。
  • 如果没有选择分类或选择了非"热门"分类,则使用随机排序(ORDER BY RAND())。
  • 使用 LIMITOFFSET 实现分页。

示例:

  • 如果用户选择"动作"分类并搜索"冒险",则:
    • 查询符合条件的游戏。
    • 按随机顺序排序。
    • 根据当前页码和每页数量,返回对应的游戏数据。

三、前端游戏列表展示

使用 Bootstrap 实现响应式布局,展示游戏列表。

html 复制代码
<div class="row">
    <?php if (empty($games)): ?>
        <p class="text-center">未找到相关游戏</p>
    <?php else: ?>
        <?php foreach ($games as $game): ?>
            <div class="col-6 col-sm-6 col-md-4 col-lg-3 mb-4">
                <div class="card h-100">
                    <a href="<?= htmlspecialchars($game['game_url']) ?>" target="_blank">
                        <img src="<?= htmlspecialchars($game['image_url']) ?>" 
                             class="card-img-top game-img" 
                             alt="<?= htmlspecialchars($game['name']) ?>">
                    </a>
                    <div class="card-body d-flex flex-column">
                        <h5 class="card-title"><?= htmlspecialchars($game['name']) ?></h5>
                        <p class="card-text flex-grow-1"><?= htmlspecialchars($game['description']) ?></p>
                        <div class="d-flex justify-content-between align-items-center">
                            <a href="<?= htmlspecialchars($game['game_url']) ?>" 
                               class="btn btn-primary" 
                               target="_blank">
                                开始游戏
                            </a>
                            <p class="mb-0">访问次数: <?= $game['clicks'] ?? 0 ?></p>
                        </div>
                    </div>
                </div>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

关键点:

  • 响应式布局 :使用 Bootstrap 的栅格系统(col-6 col-sm-6 col-md-4 col-lg-3),适配不同屏幕尺寸。
  • 游戏卡片:每张卡片包含游戏封面、名称、描述、访问次数和开始游戏按钮。
  • 安全性 :使用 htmlspecialchars 函数防止 XSS 攻击。

四、安全性注意事项

4.1 防止 SQL 注入

  • 使用 PDO 的预处理语句(preparebindValue)防止 SQL 注入。

  • 示例:

    php 复制代码
    $stmt = $pdo->prepare("SELECT * FROM games WHERE id = :id");
    $stmt->bindValue(':id', $id, PDO::PARAM_INT);
    $stmt->execute();

4.2 防止 XSS 攻击

  • 使用 htmlspecialchars 函数对用户输入的数据进行转义。

  • 示例:

    php 复制代码
    echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');

4.3 隐藏敏感信息

  • 不要将数据库账号密码直接写在代码中,可以使用环境变量或配置文件。

  • 示例:

    php 复制代码
    $username = getenv('DB_USERNAME');
    $password = getenv('DB_PASSWORD');

六、完整代码下载

1.从csdn下载:download.csdn.net/download/qq... 2.海拥资源网下载:code.haiyong.site/2041/ 3.联系博主免费获取

相关推荐
zhougl9962 小时前
html处理Base文件流
linux·前端·html
花花鱼2 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
HBR666_2 小时前
marked库(高效将 Markdown 转换为 HTML 的利器)
前端·markdown
careybobo3 小时前
海康摄像头通过Web插件进行预览播放和控制
前端
杉之5 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
喝拿铁写前端5 小时前
字段聚类,到底有什么用?——从系统混乱到结构认知的第一步
前端
再学一点就睡5 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
木木黄木木6 小时前
html5炫酷图片悬停效果实现详解
前端·html·html5
请来次降维打击!!!7 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
難釋懷7 小时前
JavaScript基础-移动端常见特效
开发语言·前端·javascript