We-Ball 是一个前后端全开源的 NBA 赛事与社交社区项目。它从数据库设计、Service 层封装,到好友关系、社区热榜,再到配套的微信小程序前端,提供了完整可运行、可修改、可直接上线的全栈解决方案。。

先看成果:后端 + 小程序,完整闭环

We-Ball 不是只写了一半的后端,而是一套可直接上线的完整产品

  • 🏀 后端 API:ThinkPHP 5.1,提供赛事数据 + 用户体系 + 社区论坛
  • 📱 微信小程序:原生开发,真机可跑,支持查看比赛、刷帖子、加好友
  • 🗄️ 数据库:MySQL 5.7+,表结构已给全
  • 📸 媒体上传:图片/视频统一入口

目前全部开源,没有任何加密,你可以直接拿去二次开发。

下面我把开发过程中 最得意的 7 个设计特点 拆开来讲,每一个都是真实踩坑后的沉淀。


一、为什么我要自己写这个项目?

市面上已有的体育类开源项目,要么是爬虫脚本,要么只提供比分 API,缺少用户沉淀的能力。而体育,尤其是 NBA ——天然就是社交话题。

我想要一个既能查数据,又能加好友、发帖子、讨论比赛的完整后端。
既然找不到,那就自己造一个。

目标很明确

  • 代码要清晰,别让接手的人骂我
  • 接口要规范,前端同学用着舒服
  • 扩展要容易,加一个新功能不改老代码
  • 最好再配一个小程序 Demo,让新手也能快速跑起来

于是 We-Ball 诞生了,而且后端 + 小程序一起开源。


二、后端架构特点(重点中的重点)

1️⃣ 分层设计:Controller → Service → Model 三层

ThinkPHP 自带 MVC,但我把业务逻辑全部抽到了 Service 层

// application/index/controller/MatchController.php
public function detail()
{
    $matchId = input('matchId');
    $data = (new MatchService())->getMatchDetail($matchId);
    return json(['code' => 200, 'msg' => 'ok', 'data' => $data]);
}

MatchService 里做数据查询、组装、缓存等。这样做的好处:

  • 控制器极薄:只负责参数校验和响应格式
  • 逻辑可复用:比如 UserService 里也能调用 MatchService 获取用户关注球队的比赛
  • 容易测试:可以单独对 Service 做单元测试

我个人建议,任何超过 20 个接口的项目都应该引入 Service 层。

2️⃣ 统一 API 响应与异常处理

所有接口返回同一个结构:

{
  "code": 200,
  "msg": "success",
  "data": {}
}

错误码统一管理(200 成功,400 参数错,401 未登录,500 服务器错)。
同时在 app.php 里关闭 debug 模式下的错误详情暴露,生产环境不会把 SQL 报错吐给用户。

3️⃣ 模块化目录:一个模块一个服务

application/index/
├── controller/
│   ├── HomeController.php
│   ├── MatchController.php
│   ├── TeamController.php
│   ├── PlayerController.php
│   ├── UserController.php      # 包含登录/好友/收藏/动态
│   ├── CommunityController.php  # 帖子/分类
│   └── MediaController.php
├── service/
│   ├── HomeService.php
│   ├── MatchService.php
│   └── ...
└── utils/
    └── utils.php                # 公共函数

新增一个功能(比如“球员对比”),就在 PlayerController 里加方法,在 PlayerService 里实现逻辑,不影响现有模块。

4️⃣ 数据库设计:不做过度设计,但要能撑住真实场景

挑几张核心表详细说:

matches 比赛表
字段 类型 说明
id int 主键
home_team_id int 主队 ID
away_team_id int 客队 ID
match_time datetime 比赛时间
home_score int 主队得分
away_score int 客队得分
status tinyint 0未开始 1进行中 2已结束

设计思路:不把技术统计塞进主表,单独用 match_stats 表存球员个人数据,避免字段爆炸。

friends 好友关系表
字段 说明
user_id 发起方
friend_id 目标方
status 0待确认 1同意 2拒绝

设计思路:只存一条记录,查询“我的好友”时用 (user_id = 某 AND status=1) OR (friend_id = 某 AND status=1),配合联合索引,性能足够。

moments 用户动态表

类似微信朋友圈,支持文字 + 最多 9 张图片(图片 ID 存在 images 字段,逗号分隔,关联 media 表)。

设计思路:简单够用,不搞复杂的多表关联,图片用 explode 拆开即可。

5️⃣ 媒体上传:统一入口,安全过滤

MediaController 提供 /media/upload 接口,支持图片和短视频:

// 前端传 file,后端校验类型
$file = request()->file('file');
$type = $this->checkFileType($file);
if (!$type) return error('不支持的文件类型');
// 按日期分目录存储:/uploads/2025/04/xxx.jpg
$path = $file->move(ROOT_PATH . 'public/uploads/' . date('Ymd'));

同时返回可访问的 URL,前端直接展示。小程序里用 wx.uploadFile 对接即可。

6️⃣ 路由配置:清晰、可维护

所有接口定义在 route/route.php

// 比赛模块
Route::get('match/list$', 'index/Match/list');
Route::get('match/detail$', 'index/Match/detail');

// 用户模块
Route::post('user/login$', 'index/User/login');
Route::get('user/friend$', 'index/User/friend');
Route::post('user/submitmoment$', 'index/User/submitMoment');

// 社区模块
Route::get('community/list$', 'index/Community/list');
Route::post('community/submitpost$', 'index/Community/submitPost');

特点:全部带 $ 结尾,严格匹配,避免 /match/list/xxx 误匹配。同时支持 GET/POST 分离,符合 RESTful 习惯。

7️⃣ 缓存与性能优化(实战经验)

  • 球队列表、球员排行榜这种不常变的数据,用 ThinkPHP 缓存 存 10 分钟,减轻数据库压力。
  • 比赛中的实时比分不做缓存,直接查库(因为前端轮询频率不高)。
  • 帖子列表用分页 + limit,避免一次查几千条。

示例代码(TeamService):

public function getRankList()
{
    $cacheKey = 'team_rank';
    $data = cache($cacheKey);
    if (!$data) {
        $data = TeamModel::order('points', 'desc')->select();
        cache($cacheKey, $data, 600); // 10分钟
    }
    return $data;
}

三、配套小程序前端:真机可跑,无缝对接

光有后端还不够,为了让整个项目真正“活”起来,我专门开发了一个完整的微信小程序前端。这样,无论是初学者还是开发者,都能立即上手体验,看到前后端联动的完整效果。让大家真正能跑起来。

小程序技术栈

  • 前端框架:基于微信小程序原生框架(MINA),使用 WXML、WXSS 和 JavaScript 进行开发。
  • UI 组件库:采用 Vant Weapp v1.11.7,提供丰富、美观且高性能的组件,加速界面开发。
  • 状态管理:主要使用小程序原生的 globalData 进行全局状态共享,并可选搭配轻量级的事件总线机制来处理跨页面通信。
  • 网络请求:对 wx.request 进行了二次封装,统一管理 API 请求的 URL、请求头、错误处理和 loading 状态,提升代码复用性和可维护性。
  • 版本控制:使用 Git 进行代码管理,并通过 .gitignore 文件忽略了 node_modulesminiprogram_npm 等非必需提交的目录,保持仓库整洁。

核心页面展示

为了让您更直观地了解小程序的功能和界面,这里展示了几个核心页面的截图:

  • 首页:赛事信息、热门帖子一目了然。
    首页

  • 社区:浏览和参与各类篮球话题讨论。
    社区

  • 我的:个人中心,管理个人信息、收藏和动态。
    我的

  • 球友圈:查看好友动态,分享篮球生活。
    球友圈

  • 我的球友:管理好友列表,添加或移除好友。
    我的球友

  • 关注的球员:查看已关注球员的最新数据和动态。
    关注的球员

  • 关注的球队:获取已关注球队的赛程和新闻。
    关注的球队

  • 帖子详情:深入参与某个帖子的讨论和互动。
    帖子详情

  • 比赛赛程:查看即将进行和已结束的比赛。
    比赛赛程

  • 好友资料:查看好友的详细信息和动态。
    好友资料

前后端对接示例

小程序里请求比赛列表:

// 小程序端
wx.request({
  url: 'https://your-domain.com/match/list',
  success: (res) => {
    if (res.data.code === 200) {
      this.setData({ matches: res.data.data });
    }
  }
});

后端返回的数据格式完全匹配,前端不需要做额外转换。
用户登录、发帖子、加好友等接口也都已联调通过。

如何本地运行小程序?

  1. 下载微信开发者工具
  2. 克隆小程序源码:git clone https://gitee.com/walii/mini-weball.git
  3. 修改 utils/config.js 里的后端域名(本地调试可以用 http://localhost:8000,但注意微信小程序的 request 合法域名需要配置 HTTPS)
  4. 真机预览或模拟器运行

如果你只想测试后端,也可以直接用 Postman 调用 API。


四、开发中踩过的 3 个大坑(附解法)

🧨 坑1:好友关系查询性能差

一开始用 (user_id = 1 OR friend_id = 1),随着数据量增大,索引失效。
解法:加冗余字段 relation_key,存 min(uid, fid)_max(uid, fid),直接等值查询。或者保持原逻辑但建联合索引 (user_id, status)(friend_id, status)

🧨 坑2:小程序登录态管理

小程序调用 wx.login 拿到 code,后端请求微信接口换取 openid,再返回自定义 token。
解法:我做了完整的 token 生成与校验,后端通过 UserService::checkToken() 统一验证,存在缓存中。

🧨 坑3:图片上传在小程序端被压缩

小程序 wx.chooseImage 默认会压缩图片,导致后端收到的图片尺寸变小。
解法:前端设置 sizeType: ['original'],后端限制最大 5MB,并压缩一遍。


五、项目亮点 VS 其他开源体育项目

特性 一般爬虫项目 We-Ball(我的项目)
用户系统 ❌ 无 ✅ 登录/好友/收藏/动态
社区帖子 ❌ 无 ✅ 完整帖子+分类+评论
API 设计 零散不规范 ✅ RESTful + 统一响应
Service 层 ✅ 业务逻辑独立
媒体上传 ✅ 图片/视频统一入口
配套前端 微信小程序,开箱即用
文档 几乎没有 ✅ 详细 README + API 表格 + 小程序文档

很多开源体育项目只提供数据,但体育天生需要人和人一起讨论。We-Ball 把“看球”和“聊球”连在一起,这才是社区的价值。


六、技术栈与快速上手指南

后端环境

  • PHP 7.0 ~ 8.0
  • MySQL 5.7+
  • Nginx / Apache
  • Composer

小程序环境

  • 微信开发者工具
  • 小程序 AppID(自己注册一个免费的)

5 分钟跑起来

# 1. 克隆后端
git clone https://gitee.com/walii/php-weball.git
cd php-weball
composer install

# 2. 配置数据库 config/database.php
# 3. 导入 SQL(仓库里有个 weball.sql)
mysql -u root -p db_weball < weball.sql

# 4. 启动后端
php think run
# 后端地址:http://localhost:8000

# 5. 克隆小程序
git clone https://gitee.com/walii/mini-weball.git
# 用微信开发者工具打开,修改 config.js 里的域名
# 真机调试(注意 localhost 只能在模拟器用,真机需配置 HTTPS 或使用内网穿透)

七、未来计划(欢迎 PR)

  • ✅ 已完成:核心 API + 小程序 Demo
  • ✅ 已完成:详细的 README 和接口文档
  • 🔲 进行中:JWT 替代 Session 认证
  • 🔲 计划中:WebSocket 实时推送比分
  • 🔲 计划中:管理后台(Vue 3 + Element Plus)
  • 🔲 计划中:支持多语言(英文/中文)

如果你对某个方向感兴趣,欢迎提 Issue 或直接 PR,一起把 We-Ball 做得更强。


八、源码获取

项目完全开源,没有任何加密、没有任何商用限制,代码随便改、随便用。

📦 后端仓库(ThinkPHP 5.1)

  • Gitee:https://gitee.com/walii/php-weball
  • 包含:完整 API 接口、Service 层代码、数据库表结构、配置文件
  • 克隆命令:git clone https://gitee.com/walii/php-weball.git

📖 使用建议

  1. 先克隆后端,配置 config/database.php,导入 SQL
  2. composer install 安装依赖
  3. php think run 启动后端
  4. 克隆小程序,修改 utils/config.js 里的后端域名
  5. 微信开发者工具打开,真机调试或预览

⚠️ 注意事项

  • 小程序 request 合法域名需要配置 HTTPS,本地调试可以用模拟器或内网穿透
  • 生产环境记得关闭 app_debug 和数据库 debug
  • 图片上传路径需要写权限:public/uploads/

💬 有问题?

  • Gitee Issues:直接提
  • 欢迎 PR,欢迎 Star,欢迎 fork 自己魔改

九、写给读者的话

开源一个完整的项目并不容易,从设计到编码到写文档,再到写一个小程序 Demo,前前后后花了几百个小时。
但当你看到有人在 Issue 里认真提问,甚至有人 Star 时说“这能直接拿去接小程序”,那种感觉确实很爽。

如果你也是 PHP 开发者,或者体育爱好者,或者小程序初学者,欢迎:

  • ⭐ Star 支持后端:https://gitee.com/walii/php-weball
  • ⭐ Star 支持小程序:https://gitee.com/walii/mini-weball
  • 🐛 提 Bug / 建议
  • 🍴 Fork 自己改一个版本

也欢迎在评论区聊聊:你理想中的体育社区应该有什么功能?

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐