验证码图片不显示的根本原因是php输出缓冲控制不当,session_start()或echo提前发送http头导致imagejpeg()失败;配色不当致文字不清、session未更新致刷新不变、gd扩展未启用致函数不存在。

验证码图片不显示,imagejpeg 报错“headers already sent”
根本原因是 PHP 输出缓冲没控制好,session_start() 或 echo 语句提前触发了 HTTP 头发送,导致 imagejpeg() 无法写入响应头。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 确保验证码生成脚本(如
captcha.php)开头没有空格、bom、echo、print或session_start()前的任何输出 - 如果用了
session_start(),必须放在文件最顶部,且前面不能有任何字符(包括 UTF-8 BOM) - 临时调试时加一句
ob_end_clean();在header("Content-type: image/jpeg")之前,能快速绕过缓冲干扰(但别长期依赖) - 用编辑器检查文件编码:必须是「UTF-8 无 BOM」,Notepad++ 或 VS Code 都可设
验证码文字看不清或全黑,imagecolorallocate 和 imagestring 配色出问题
常见于背景色和文字色没做反差处理,比如都用深色,或文字颜色被错误地设成背景同色。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先用
imagecolorallocate($img, 255, 255, 255)设白色背景,再用imagecolorallocate($img, 0, 0, 0)设黑色文字——这是最稳妥的起手配色 - 避免直接用
rand(0,50)给 RGB 三通道,容易撞上相近灰度;改用明暗分离策略:$text_color = imagecolorallocate($img, rand(50,100), rand(50,100), rand(50,100))配浅灰背景更可靠 -
imagestring的坐标要留边,比如imagestring($img, 5, 10, 15, $code, $text_color),否则文字可能被截掉
验证码刷新后不变,$_SESSION['captcha_code'] 没更新或被覆盖
典型场景是多个地方写了 $_SESSION['captcha_code'] = ...,或者 session 没正确开启/读取,导致表单校验时比对的是旧值。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 生成验证码的脚本里,赋值前加
session_start();,赋值后立刻用exit;结束脚本(防止后续意外输出) - 不要在验证码生成页里做校验逻辑——它只负责画图 + 存 session;校验动作必须放在表单提交的目标脚本中(如
login.php) - 调试时加一句
var_dump($_SESSION['captcha_code']);看是否真存进去了,注意 CLI 下 session 不生效,得用浏览器访问 - 如果用了框架或公共配置,检查是否有自动 session write close 机制,可能让
$_SESSION写入延迟
GD 扩展未启用,Call to undefined function imagecreate()
不是代码写错了,是环境缺 GD 库——PHP 默认不强制安装图像处理扩展,尤其 docker 或某些精简版 PHP。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 命令行运行
php -m | grep gd,没输出就说明没开;linux 下通常执行sudo apt install php-gd(debian/ubuntu)或sudo yum install php-gd(centos) - windows 用户检查
php.ini是否有;extension=gd,去掉分号并确认extension_dir路径正确 - 重启 Web 服务(
sudo systemctl restart apache2或sudo service php-fpm restart),光重启 PHP-FPM 不够,Apache/nginx 也要重载 - 验证是否生效:新建
info.php,内容为<?php phpinfo(); ?>,浏览器打开后搜 “gd”,看到 enabled 才算到位
真正麻烦的不是画不出图,而是 session 和输出缓冲在背后悄悄打架;只要确保脚本干净、GD 可用、session 启动时机准确,剩下的就是调几个 rand() 和 imagestring() 参数的事。