thinkphp集成验证码需装对think-captcha扩展并启用session中间件;图像输出用{:captcha_img()}或严格无输出路由;校验失败主因是输入为空、session id不一致或验证码已消耗。

新手在ThinkPHP项目中集成验证码,核心就两点:扩展装对、Session跑通。缺一不可,否则图像空白、校验永远失败。
必须手动安装并启用 think-captcha 扩展
ThinkPHP 5.1 起验证码已移出核心,不能直接 new Captcha() 就用。得先执行:
- composer require topthink/think-captcha 安装扩展包
- 打开 app/middleware.php,取消注释
\think\middleware\SessionInit::class—— TP6 默认是注释掉的,不取消就等于没开 Session - 别在控制器里写
session_start(),那没用;必须靠中间件自动初始化,才能让$_SESSION可读可写
验证码图像要“稳”输出,别自己 echo 或 return 图片流
直接在控制器方法里 return (new Captcha())->create() 很容易因模板输出、空格、header 冲突导致图片损坏(浏览器显示“无法加载”)。推荐两种稳妥方式:
- 前端模板用
{:captcha_img()},它自动生成带时间戳参数的<img src="/captcha?_=1748932080">标签 - 若需自定义路由,如
Route::get('mycode', [\think\captcha\facade\Captcha::class, 'create']);,该方法体内不能有任何输出(包括 var_dump、echo、甚至换行符),否则 PNG 流被破坏
校验失败?先查这三件事
90% 的 check() 返回 false 不是代码写错,而是环境或调用链出了问题:
-
用户输入为空或全是空格:前端提交前建议
trim(),后端也做一次$input = trim($input) - Session ID 不一致:登录页和提交页用了不同子域名(如 login.example.com vs api.example.com),或跨域请求,导致两次请求 session_id() 不同,存一份、查另一份
-
验证码已被消耗:ThinkPHP 默认一次性有效,
check()成功后立即清除 session 中的值;若 JS 重复提交、或用户刷新页面后重输旧验证码,必然失败
大小写与中文配置别踩坑
默认 check 区分大小写。如果生成的验证码含大写字母 A-Z,而用户习惯全小写输入,校验就会失败:
- 统一转大写再比对:
(new Captcha())->check(strtoupper($input)) - 或配置禁用中文、关闭大小写敏感:
$config = ['useZh' => false, 'reset' => true],传入构造函数 - 需要中文验证码时,务必指定中文字体路径(如
msyhbd.ttf)并设useZh => true,否则乱码或报错
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











