最省事方式是在模板中直接使用{:captcha_img()},它自动生成带时间戳防缓存的img标签并内置点击刷新逻辑;需确保GD扩展、Session中间件已启用且域名匹配。

前端模板里直接用 captcha_img() 最省事
不需要自己拼 URL、写 onclick 刷新逻辑,captcha_img() 是 think-captcha 提供的助手函数,它会自动输出带时间戳防缓存的 <img> 标签。只要扩展已安装、Session 已启用、GD 扩展开着,一行就搞定:
<div>{:captcha_img()}</div>
渲染后实际 HTML 类似:<img src="/captcha?_=1724728460" title="点击更新验证码" alt="点击更新验证码" onclick="this.src='/captcha?_'+Math.random()">。注意它默认已绑定点击刷新,无需额外 JS。
手动写 <img src> 时必须确保路由存在且纯净输出
如果你不用 captcha_img(),而是想自定义路径(比如 /index/captcha),那控制器里必须提供一个**只返回图像流、无任何其他输出**的方法:
- 在控制器中添加方法:
public function captcha() { return \think\captcha\facade\Captcha::create(); } - 确保该方法所在控制器没加载任何模板、没 echo/var_dump/空格,否则图像二进制流会被破坏,浏览器显示“损坏的图像”
- 模板中调用:
<img src="{:url('index/captcha')}" alt="验证码" onclick="this.src='{:url('index/captcha')}?'+Math.random()">
页面有多个验证码时必须传 $id 参数
比如登录页和注册页共存,或同一页面两个表单,得用不同 ID 隔离 Session 值,否则互相干扰:
立即学习“PHP免费学习笔记(深入)”;
- 生成时:
{:captcha_img('login')}或{:captcha_img('register')} - 校验时:
captcha_check($input, 'login')或captcha_check($input, 'register') - 不传 ID 默认用
default,所有未指定 ID 的调用都共享同一个 Session 键
常见失败原因:不是前端调用错,而是后端链路断了
前端 <img> 标签明明写了,却一直空白或 500 —— 90% 是下面三件事没做对:
-
php.ini没开extension=gd,导致imagecreate()函数不存在,检查方式:var_dump(extension_loaded('gd'))必须输出bool(true) -
app/middleware.php里\think\middleware\SessionInit::class还被注释着,Session 不初始化,验证码值根本存不进 $_SESSION - 你改过
config/session.php的domain或secure,但前端访问域名和后端 Cookie 域不匹配(比如用localhost访问,但 session domain 设成了.example.com)
真正卡住的地方往往不在前端怎么写,而在 GD 是否可用、Session 是否真通、域名是否一致——这些不验证清楚,前端无论怎么换写法都没用。



















