推荐使用 mews/captcha 插件,它专为 laravel 封装、支持 facade 和配置发布;安装后需执行 vendor:publish 命令并确保服务提供者注册、配置缓存清除、路由置于 web 组且 session 驱动可靠。

怎么选对验证码插件(Laravel 场景下)
Composer 安装的验证码插件五花八门,但真正在 Laravel 项目里能跑通、不报 Class not found、不和 php artisan serve 冲突的其实就几个。最稳的是 gregwar/captcha 和 mews/captcha,前者轻量无框架依赖,后者专为 Laravel 封装、带 Facade 和配置发布,推荐新手直接用 mews/captcha。
别碰那些标着 “Laravel 9+ only” 却没更新到 2024 年的包,容易卡在 illuminate/support 版本上;也别用纯原生 PHP 的 captcha 类手动 require —— Composer 自动加载机制会绕过它,Captcha::create() 这类调用直接报错。
-
composer require mews/captcha是当前 Laravel 10/11 兼容性最好的命令 - 安装后必须执行
php artisan vendor:publish --provider="Mews\Captcha\CaptchaServiceProvider",否则配置文件不会落地到config/captcha.php - 如果项目启用了 Laravel Pint 或 PHPStan,注意该包默认生成的
captcha.php里有注释掉的'length' => 4,实际生效得取消注释
为什么 captcha() 函数找不到
装完插件却在 Blade 里写 @captcha 或控制器里调 captcha() 报错,大概率是服务提供者没注册或别名没配。这不是 Composer 没装好,是 Laravel 的自动发现机制被关了,或者你用的是 Laravel 8 以下版本(不支持自动发现)。
检查 config/app.php 里的 providers 数组是否含 Mews\Captcha\CaptchaServiceProvider::class,aliases 里有没有 'Captcha' => Mews\Captcha\Facades\Captcha::class。Laravel 5.5+ 默认开启自动发现,但如果你执行过 composer install --no-plugins,这个机制就废了。
- 运行
composer dump-autoload强制刷新类映射(尤其换分支或重装依赖后) - 确认
APP_DEBUG=true,否则Class 'Captcha' not found这种错误会被静默吞掉,只显示 500 - Blade 中用
@captcha前,确保已执行过php artisan config:clear,否则旧缓存可能让captcha.php配置不生效
图形验证码图片不显示(404 或空白)
浏览器开发者工具看到 /captcha/default 返回 404,或者返回空响应但没报错,说明路由没注册或中间件拦截了。Laravel 6+ 默认关闭了全局 web 中间件组自动绑定,而 mews/captcha 的路由必须走 web 才能维持 session —— 图形验证码本质靠 session ID 关联输入值。
打开 vendor/mews/captcha/src/CaptchaServiceProvider.php,看它的 mapWebRoutes() 是否被调用;更简单的方法:在 routes/web.php 末尾手动加一行 Route::get('/captcha/{config?}', [\Mews\Captcha\CaptchaController::class, 'getCaptcha'])->name('captcha');,然后清缓存。
- 别把验证码路由写在
api路由文件里 ——api默认不启用 session,getCaptcha()会返回空 PNG - 如果用了 Nginx,检查是否误配了
location ~ \.php$规则,导致/captcha/*请求没进 PHP-FPM - 验证码图片 URL 必须带域名(如
https://yoursite.com/captcha/default),不能是相对路径/captcha/default后接 Ajax 请求,否则跨域或协议不匹配时图片加载失败
验证失败却没提示($request->validate() 不拦)
表单提交后明明输错了验证码,$request->validate(['captcha' => 'required|captcha']) 却没触发错误,页面直接跳走。问题出在验证规则注册时机:Laravel 的 captcha 规则不是内置的,它依赖 mews/captcha 的服务提供者在启动阶段注册该规则。如果服务提供者加载顺序晚于验证器初始化(比如某些自定义 Service Provider 改动了 boot 顺序),规则就丢了。
最直接的验证方式是临时在控制器里加一句 dd(Captcha::check($request->input('captcha')));,返回 false 就说明后端校验逻辑本身没问题,问题在 validate() 的规则链没挂上。
- 执行
php artisan config:clear && php artisan cache:clear,再试 —— 配置缓存可能锁住了旧的验证规则注册状态 - 检查
app/Providers/AppServiceProvider.php的boot()方法里有没有调用Validator::extend(...),它会覆盖默认规则注册流程 -
captcha规则严格区分大小写,且要求字段名必须叫captcha;如果表单传的是code,得写成'code' => 'required|captcha'并确保前端 name 属性一致
session 驱动用 file 时,如果部署在多台机器上没共享存储,验证码必然失效;换成 redis 或 database 才算真正可用。这点很多人等到上线才踩坑。










