做Shot系统的一些想法
Shot 是一个纯原生 PHP 构建的摄影作品展示与社区平台。没有 Composer 框架,没有前端构建链,把上传、处理、审核、展示到互动的整条链路自己走完——界面退到幕后,把注意力全还给照片本身。
照片其实很挑容器。
放进通用 CMS,它会被压成统一尺寸的缩略图,拍摄参数被悄悄剥掉;发到社交平台,它要跟信息流、广告和一排按钮抢注意力。想自己搭一套,又很容易变成一堆互相打补丁的脚本:上传能用了,审核没有;瀑布流好看了,权限又漏了。
Shot 想解决的正是这件事:给摄影作品一个不抢戏、但每个环节都完整的家。它用 PHP 8 原生代码 + MySQL 写成,MVC 分层、零框架依赖,从用户点下「上传」到作品出现在首页瀑布流,中间所有步骤都由系统自己完成。
01 让照片成为唯一的主角
第一眼的克制,是这个平台最在意的部分。
暗色画布。 整套界面用 CSS 变量统一管理,近黑底色配紫罗兰点缀(主色 #8b5cf6)。没有高亮边框、没有花哨卡片去和作品抢对比度,照片的色彩与明暗得以保持原样。
全屏首屏,每次打开都是新封面。 系统从「浏览量 + 点赞 + 收藏 + 评论」综合评分前 10 名的照片里随机选一张,铺满 100vh 作为背景,配合鼠标跟随视差(±20px 平移、1.05× 缩放)和随滚动自动切换透明度的导航栏。左下角只留一行作者与数据,精选结果落盘缓存 6 小时,既保持新鲜感又不反复查库。
不依赖任何库的瀑布流。 最新作品用 CSS Multi-column 加原生 JS 的 Round-robin 均分算法排布,桌面 6 列、平板 5 列、手机 3 / 2 列随宽度变化,图片统一懒加载。不用 Masonry、不用构建工具,底部还能裁出整齐的视觉边界。桌面、平板、手机一套代码自适应。

详情页把故事讲完整。 大图之外,上下张导航、原图查看、点赞收藏、评论与 EXIF 参数收在同一屏。拍摄参数优先读数据库里 photos.exif 的 JSON 字段,缺失时才实时从文件解析,兼顾准确与兼容。
02 一张原片进去,四档尺寸出来
上传不是「把文件存进目录」就结束了。系统会校验登录状态、邮箱、存储配额、MIME 类型与文件大小,按 YYYY/MM/DD 分目录归档,然后自动完成整套图片处理:
| 档位 | 规格 | 用在哪 |
|---|---|---|
| 原图 | 用户上传文件完整保留 | 详情页「原画」一键加载 |
| 大图 | 最长边 1920px | 照片详情页、灯箱放大 |
| 封面 | 宽度 800px | 相册卡片、分类页、精选位 |
| 缩略图 | 宽度 400px | 瀑布流、列表,配合懒加载 |
处理过程会自动按 EXIF Orientation 标签矫正方向(8 种方向),支持 WebP / AVIF,并保留 PNG 透明通道。
EXIF 在这里是硬性门槛,不是附加信息。 上传时强制校验照片是否含相机品牌型号,无 EXIF 的照片直接拒收并清理已上传文件;通过后再解析相机、镜头、光圈、快门速度、ISO、焦距、拍摄时间,以 JSON 入库。详情页把相机 / 镜头 / 光圈 / 快门 / ISO / 焦距 / 拍摄时间 / 画面尺寸八项参数完整呈现——对摄影作品来说,这些数字本身就是作品的一部分。
03 审核不是补丁,是一条有状态的流水线
内容平台最容易在「谁来把关」这件事上含糊。Shot 把审核做成了明确的状态机:
flowchart LR
A[上传<br/>校验与归档] --> B[处理<br/>四尺寸 + EXIF]
B --> C[待审 pending<br/>普通用户作品]
C --> D{审核}
D -->|通过| E[approved<br/>前台可见]
D -->|拒绝| F[rejected<br/>回传原因]
E --> G[聚合邮件通知作者<br/>进入瀑布流]如果博客平台不支持 Mermaid,直接写成一行即可:上传 → 处理(四尺寸 + EXIF)→ 待审 → 审核(通过 / 拒绝)→ 展示与通知
几个真正省时间的细节:
- 按相册分组:待审照片以相册为单位展示,一次看完整组作品,而不是散落的单图列表。
- 批量操作:单张通过/拒绝、整册全部通过或拒绝、跨相册多选拒绝都支持,缩略图可点开灯箱放大核对细节与 EXIF 摘要。
- 聚合通知:批量操作只发一封邮件,列出通过数量与拒绝清单及原因,不会把作者邮箱刷屏。
- 封面有门槛:只有审核通过的作品才能被设为相册封面。
- 权限隔离:版主通过
user_categories绑定到指定分类,只能审核自己负责的分类;管理员统管全部。管理员与版主自己上传的作品可直接进入已通过状态。
配套的是自研 SMTP 通知体系:SSL / TLS、HTML 与纯文本双格式,覆盖注册验证码、邮箱验证、审核结果、新作品提醒,后台可一键发测试邮件验证配置。
04 十二项能力,一次看清
| 方向 | 能力 | 关键点 |
|---|---|---|
| 展示 | 全屏精选首屏 / 自适应瀑布流 / 全端响应式 | Top 10 随机选片、6→5→3→2 列、纯 CSS Columns |
| 内容 | EXIF 全链路 / 四尺寸图片管线 | 无 EXIF 拒收、8 项参数、方向自动矫正、按日期归档 |
| 治理 | 审核工作流 / 四级角色权限 / 立体安全防线 | 相册分组批量、分类级隔离、CSRF + bcrypt + PDO + 三重上传校验 |
| 账号 | 两步验证码注册 / SMTP 通知 | 6 位验证码 10 分钟有效,校验即验邮箱,自动登录 |
| 社区 | 点赞 / 收藏 / 评论 / 搜索 / 标签 / 排行榜 | 评论 AJAX 10 条/页、五种排序维度、用户主页 |
| 后台 | 独立管理入口 | 仪表盘、用户/分类/相册/照片/评论管理、审核台、SEO、站点 Logo、SMTP、友情链接 |
| 工程 | 零框架 / 多层缓存 / 懒加载 | 热门照片缓存 6 小时、设置项请求级内存缓存、MVC + 前端控制器 |
注册流程值得一提:输入邮箱 → 收到 6 位验证码(10 分钟有效)→ 填资料 → 自动登录。不用跳去邮箱点验证链接,校验通过即视为邮箱已验证,也支持重新发送。一个很小的设计,但注册转化率差别很大。
安全上也没有因为「是个人项目」就省事:全站 POST 带 CSRF Token、密码 bcrypt 哈希、全量 PDO 参数化查询、全局 esc() 输出转义,上传环节再做 MIME 类型 + 扩展名 + EXIF 三重校验,专门防伪装文件。
05 分类不限量,结构由你自己定
这一点需要特别说明:分类不是固定数量,也不预设上限。
演示站里能看到动物、人像、风景、街拍、微距、黑白、古风、旅途等十几个标签,那只是当前这份演示数据的配置。后台可随时创建、编辑、排序与删除分类,想按器材分、按拍摄年份分、按项目分,或者一个分类都不建,都随你。前台分类卡片支持横向拖拽浏览,数量多了也不会挤成一团。
相册、封面、可见性(草稿 / 公开 / 私密)同样由后台和使用者自己配置。换句话说,Shot 交付的是一套可塑的内容结构,而不是一套替你决定好该怎么分类的产品。

06 技术架构:简洁,但不将就
| 层级 | 选型 |
|---|---|
| 后端 | PHP 8.x 原生,零框架,PSR-4 风格自动加载 |
| 数据库 | MySQL 8.x,InnoDB / utf8mb4 |
| 前端 | HTML5 + CSS3 + 原生 JS(CSS 变量、Flexbox / Grid / Columns) |
| Web 服务 | Nginx + PHP-FPM,Linux / 宝塔面板 |
| 扩展要求 | GD(图片处理)、EXIF(参数解析)、Fileinfo(MIME)、OpenSSL(邮件加密) |
请求链路很直白:
Nginx → PHP-FPM
→ 前端控制器 public/index.php(注册 GET / POST / PUT / DELETE 路由)
→ Router 分发(解析路径参数、匹配控制器方法)
→ Controller(认证、上传、审核、互动)
→ Model(基类 CRUD + PDO 参数化查询)
→ View(前台 / 后台双布局,模板直出 HTML)用到的设计模式都很朴素:MVC 分层、Database 单例、Model 基类静态工厂、前端控制器统一分发、Settings 以 Key-Value 形式存配置(支持自动迁移,改 SEO 与 SMTP 不用动代码)。
为什么坚持零框架? 摄影站的核心是图片与阅读体验,不是业务逻辑的复杂度。去掉框架和构建链之后,部署只需要一个可写目录和一份数据库;而图片管线、审核、权限这些真正要紧的部分全部自己写,可以逐行核对、随时改。对一个要长期自己维护的站点来说,「看得懂」比「用得新」更值钱。
07 数字速览
| 数字 | 含义 |
|---|---|
| ∞ | 分类数量不限,后台自由增删排序 |
| 6 → 2 列 | 响应式瀑布流列数(桌面 6 / 平板 5 / 手机 3、2) |
| 4 档 | 原图、1920px、800px、400px 自动生成的图片规格 |
| 8 项 | 详情页完整呈现的 EXIF 拍摄参数 |
| 4 级 | 管理员 / 版主 / 普通用户 / 摄影师角色权限 |
| 10 条 / 页 | 评论 AJAX 无刷新分页 |
| 6 小时 / 10 分钟 | 热门内容缓存时长 / 注册验证码有效期 |
| 0 | 第三方框架依赖 |
08 适合谁,怎么开始
- 独立摄影师:把作品集、拍摄参数、访客反馈放在自己的域名下,不必受平台压缩与排版限制。
- 摄影社团 / 俱乐部:用分类 + 相册 + 版主分类级审核,让多人投稿也能有序运作。
- 小型图片社区:点赞、收藏、评论、排行榜、搜索、验证码注册与审核台都是现成的。
- 二次开发底座:零框架、MVC 分层、代码可读,想接对象存储、加水印或改审核规则,都能直接下手。
部署不复杂:导入 migrations 建表 → 配置 .env(数据库、站点地址、运行环境)→ 给 public/uploads/ 写权限 → Nginx 站点根目录指向 public/ → 进后台完成初始化设置。PHP 8.0+ 与 MySQL 8.0+ 即可,无需 Composer、无需 Node 构建。

写在最后
做 Shot 的取舍其实只有一条:把复杂度留给系统,把安静留给照片。 上传、校验、处理、审核、通知这些环节一个都不省,但用户看到的,应该始终只有一张被好好对待的照片。

评论 (0)