php+mysql 搭建一个在线游戏网站目前已有2000+游戏

游戏PHPMySQL

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

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

picture.image

项目概述

1. 功能特点

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

2. 技术栈

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

一、数据库设计与连接

1. 表结构

数据库包含以下表:

1.1 games

存储游戏的基本信息。

字段名类型说明
idINT游戏 ID
nameVARCHAR(255)游戏名称
descriptionTEXT游戏描述
game_urlVARCHAR(255)游戏链接
image_urlVARCHAR(255)游戏封面图链接
clicksINT点击次数

1.2 categories

存储游戏分类信息。

字段名类型说明
idINT分类 ID
category_nameVARCHAR(255)分类名称

1.3 game_category

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

字段名类型说明
game_idINT游戏 ID
category_idINT分类 ID

2.使用 PDO 连接 MySQL

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

<?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 获取分类和搜索条件

$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 分页设置

$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 查询

$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 为:
    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 执行查询并获取总游戏数

$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 热门游戏逻辑

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 其他分类逻辑

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 实现分页。

示例:

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

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
火山引擎 EMR 基于 Proton 的存算分离实践
EMR 团队针对这些挑战自研了 Proton 加速引擎,深度优化对象存储读写能力,与 Hive/Spark/Trino 等计算引擎集成后,在不改变用户使用习惯的前提条件下,可提供对象存储数据集的透明加速服务。在离线场景下,其性能基本持平存算一体架构。本次分享将介绍 Proton 技术能力和最佳实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论