CodeIgniter验证码中文乱码的根本原因是默认字体不支持中文,需显式指定含中文字符的UTF-8字体文件(如simhei.ttf),并确保字体路径正确、可读且PHP文件编码为UTF-8无BOM。

CodeIgniter 的验证码(captcha)中文显示乱码,根本原因不是 GD 库没启用,而是默认字体路径指向了一个不支持中文的字体文件,且框架未提供自动 fallback 机制。
验证码中文乱码是因为找不到中文字体
CodeIgniter 2/3 的 create_captcha() 函数底层调用 GD 的 imagettftext(),必须指定一个有效的 .ttf 字体文件路径。它默认使用 system/fonts/texb.ttf(TeX Gyre Bonum),这是西文字体,不含中文字符集,遇到中文就会渲染为空白或方块。
- 即使 PHP 启用了
gd扩展、mbstring和iconv,只要字体不支持中文,照样乱码 -
create_captcha()不校验字体是否真能画出传入的中文字符串,失败时也无 warning 或 error 抛出 - 常见现象:验证码图片生成成功,但中文全显示为“口口口口”或空白,
$_SESSION或数据库里存的验证码值却是对的
手动指定中文字体路径并验证有效性
不能只改配置项,必须确保字体文件存在、可读、且含中文 glyph。推荐用 Noto Sans CJK SC(开源免费,覆盖简体中文)或系统自带的 simhei.ttf(Windows)/STHeiti Light.ttc(macOS)。
- 把字体文件放到项目内,比如
application/fonts/simhei.ttf,避免依赖系统路径 - 在调用
create_captcha()前,显式传入'font_path'参数:$vals = array( 'word' => '你好验证码', 'img_path' => './captcha/', 'img_url' => base_url().'captcha/', 'font_path' => APPPATH.'fonts/simhei.ttf', // ← 关键 'img_width' => '150', 'img_height' => 40, ); $cap = create_captcha($vals); - 务必检查该字体文件权限(web 用户需有 read 权限),并用
file_exists()+is_readable()预判:$font = APPPATH.'fonts/simhei.ttf'; if (!file_exists($font) || !is_readable($font)) { log_message('error', 'Captcha font not found or unreadable: '.$font); }
GD 中文渲染还依赖字符编码一致性
字体只是条件之一;如果传入 create_captcha() 的 'word' 是 GBK 编码,而 PHP 文件本身是 UTF-8,GD 会把字节流当乱码处理——结果仍是空白。
- 确保生成验证码的 PHP 文件保存为
UTF-8 without BOM(Notepad++ / VS Code 右下角可查) -
'word'值必须是 UTF-8 编码的字符串;若从数据库或 POST 读取,先确认来源编码:$word = mb_convert_encoding($input, 'UTF-8', 'auto');
- 不要用
iconv('GBK', 'UTF-8', $word)硬转,除非你 100% 确定源是 GBK;mb_convert_encoding(..., 'auto')更稳妥 - GD 自身不处理编码转换,它只按字节序列查字体 glyph 表,错一个字节就跳不到正确字形
CI3 中 image_lib 水印中文乱码是同一根源
如果你在用 $this->image_lib->watermark() 加中文水印也出现方块,问题完全一致:'wm_font_path' 指向了非中文字体,或 'wm_text' 编码不匹配。
- 配置中必须显式设置:
$config['wm_font_path'] = APPPATH.'fonts/simhei.ttf';
-
'wm_text'同样要 UTF-8,且长度不宜过长(GD 对长文本排版支持弱,易截断) - 注意
image_lib不会因字体缺失而报错,$this->image_lib->watermark()返回true也不代表文字画出来了——得肉眼检查输出图片 - 调试时临时加一句:
var_dump(gd_info());确认"FreeType Support"是true,否则连 TTF 都不支持
最常被忽略的一点:字体文件名里有空格或中文路径,imagettftext() 在某些 PHP/GD 版本下会静默失败。坚持用纯英文路径 + 英文文件名,哪怕多建一层 fonts/zh/ 子目录,也比冒险用 思源黑体.ttf 强。

















