erikwang2013/poster-php
Composer 安装命令:
composer require erikwang2013/poster-php
包简介
PHP captcha (click/rotate/slider) and poster generation — framework-agnostic with adapters for Laravel, ThinkPHP, Webman, Hyperf.
README 文档
README
PHP 图片验证码与海报生成工具包 —— 框架无关核心 + Laravel / ThinkPHP / Webman / Hyperf 适配。
功能
验证码(三种方式 + 随机切换)
| 类型 | 说明 |
|---|---|
点击验证 click |
用户按顺序点击图片上的目标文字 |
旋转验证 rotate |
用户拖动滑块将图片旋转回正确角度 |
滑块验证 slider |
用户拖动拼图块到缺口位置 |
随机切换 random |
随机选取以上三种验证码之一 |
海报生成
链式 Builder API,支持 14 种元素:
| 元素 | 方法 | 说明 |
|---|---|---|
| 文字 | addText() |
自动换行,对齐,多行 |
| 图片 | addImage() |
缩放裁剪,圆角,阴影 |
| 头像 | addAvatar() |
圆形裁剪,边框 |
| 二维码 | addQrcode() |
纯 PHP 生成,中心 Logo,底部文案 |
| 形状 | addShape() |
矩形/圆形/圆角,填充/描边 |
| 分割线 | addLine() |
颜色,宽度 |
| 水印 | addWatermark() |
平铺文字,角度,间距 |
| 表格 | addTable() |
表头,斑马纹,列宽 |
| 图表 | addChart() |
柱状图 / 折线图 / 饼图 |
| 日历 | addCalendar() |
月历,高亮日期,标注 |
| 艺术字体 | addArtisticText() |
描边 / 阴影 / 渐变 / 霓虹 |
| Emoji | addEmoji() |
彩色 emoji 表情渲染 |
| 字体图标 | addIcon() |
FontAwesome 图标渲染 |
| 颜文字 | addEmoticon() |
日式颜文字 / 自定义表情 |
安装
composer require erikwang2013/poster-php
系统要求:PHP >= 8.0,GD 扩展。
可选扩展:
ext-imagick:ImageMagick 图像驱动(性能更好,功能更强)ext-redis:Redis 验证码存储(分布式部署)
使用说明
一、验证码
1. 点击验证码 (ClickCaptcha)
用户需要按顺序点击图片上的目标文字(如"树""鸟""花"),验证人类操作。
// 通过辅助函数(框架无关) $result = captcha_create('click', [ 'difficulty' => 'medium', // 'easy'(2目标) | 'medium'(3目标) | 'hard'(4目标) 'background' => null, // 自定义背景图路径,null=程序化渐变背景(随机风格) ]); // 返回结果 // $result = [ // 'key' => 'abc123...', // 验证唯一标识,传给前端 // 'image' => 'data:image/png;base64,...', // 图片 base64 // 'extra' => [ // 'targets' => [ // ['order' => 1, 'text' => '树', 'x' => 120, 'y' => 80], // ['order' => 2, 'text' => '鸟', 'x' => 200, 'y' => 150], // ['order' => 3, 'text' => '花', 'x' => 310, 'y' => 95], // ], // ], // ]; // 前端根据 targets 渲染提示文字,用户依次点击对应位置 // 前端提交用户点击坐标 [[x1,y1], [x2,y2], [x3,y3]] $pass = captcha_verify($result['key'], 'click', [[120, 80], [200, 150], [310, 95]]); // 返回 true / false,容差半径 18px // 通过 CaptchaManager(完整 API) use Erikwang2013\Poster\Captcha\CaptchaManager; use Erikwang2013\Poster\Drivers\DriverFactory; use Erikwang2013\Poster\Storage\FileStorage; $manager = new CaptchaManager(DriverFactory::create(), new FileStorage()); $captcha = $manager->create('click') ->setDifficulty('hard') ->setTargetCount(4) // 自定义目标数量 1-5 ->setTargetType('text') // 'text' 文字 | 'icon' 图标 ->setBackground('/path/to/bg.jpg'); $result = $captcha->generate(); $pass = $manager->verify($result['key'], [ 'type' => 'click', 'data' => [[120, 80], [200, 150], [310, 95], [180, 60]], ]);
2. 旋转验证码 (RotateCaptcha)
系统随机旋转图片 30°~330°,用户拖动滑块将图片旋转回正。
// 通过辅助函数 $result = captcha_create('rotate'); // $result['extra'] 不含角度(验证答案),前端只展示旋转后的图片 $pass = captcha_verify($result['key'], 'rotate', 185); // 用户旋转角度,±5° 容差 // 通过 CaptchaManager $captcha = $manager->create('rotate') ->setAngleRange(45, 315) // 自定义旋转角度范围 ->generate();
3. 滑块验证码 (SliderCaptcha)
系统从背景切出拼图块并偏移,用户拖动拼图到缺口位置。
// 通过辅助函数 $result = captcha_create('slider'); // $result = [ // 'image' => '...', // 带缺口的背景图 // 'extra' => [ // 'puzzle' => '...', // 拼图块图片 // 'puzzle_w' => 50, // 拼图宽度 // 'puzzle_h' => 50, // 拼图高度 // ], // ]; $pass = captcha_verify($result['key'], 'slider', 173); // 用户滑动的 x 像素,±4px 容差
4. 随机切换 (RandomCaptcha)
系统随机从 click / rotate / slider 中选取一种验证码,增加破解难度。
// 通过辅助函数 — 一行代码随机生成 $result = captcha_create('random'); // $result['type'] 返回实际选中的类型: 'click' | 'rotate' | 'slider' // 前端根据 type 渲染对应的交互组件 switch ($result['type']) { case 'click': // 渲染点击组件:展示图片,用户依次点击 targets break; case 'rotate': // 渲染旋转组件:展示图片,用户拖动旋转 break; case 'slider': // 渲染滑块组件:展示缺口图 + 拼图块 break; } // 验证时传入实际类型和用户操作数据 $pass = captcha_verify($result['key'], $result['type'], $userData); // click: $userData = [[x1,y1],[x2,y2],...] // rotate: $userData = 185 (角度) // slider: $userData = 173 (像素) // 通过 CaptchaManager $captcha = $manager->create('random')->generate(); $pass = $manager->verify($captcha['key'], [ 'type' => $captcha['type'], 'data' => $userData, ]);
验证安全特性
| 特性 | 说明 |
|---|---|
| 一次性 | 验证成功/超过最大次数后 key 删除 |
| 防暴力 | 默认最多验证 3 次(可配置) |
| 有效期 | 默认 300 秒(可配置) |
| 随机性 | 每次生成的背景颜色、噪声、目标位置均随机 |
| 背景美化 | 程序化渐变背景,三种风格(简约/活泼/自然)随机切换,支持配置默认背景图目录 |
背景图片配置
验证码背景支持三级优先级:
- 单张图片 — 通过
setBackground('/path/to/bg.jpg')指定 - 图片目录 — 配置
captcha.background_dir指向图片目录,默认指向assets/backgrounds/(内置 6 张精美渐变背景图) - 程序化生成 — 设
background_dir为null时启用,三种风格随机切换
// 方式一:代码指定单张图片 $captcha = $manager->create('click')->setBackground('/path/to/bg.jpg'); // 方式二:替换默认背景图(config/poster.php) 'captcha' => [ // 把自己的背景图放到这个目录,自动随机选用 'background_dir' => '/path/to/my-backgrounds', // 设为 null 则使用程序化渐变背景 // 'background_dir' => null, ], // 方式三:什么都不做,自动使用内置默认背景图(assets/backgrounds/)
默认背景图:assets/backgrounds/ 自带 6 张 400×250 PNG 渐变背景,风格包括蓝紫、日落、清新绿、暗黑、粉彩、海洋蓝。
三种程序化风格:
| 风格 | 说明 |
|---|---|
minimal 简约 |
柔和渐变 + 大尺寸低透明度圆形 + 几何线条 + 稀疏细点 |
vibrant 活泼 |
明亮渐变 + 多种大小彩色圆形 + 中等密度噪点 |
natural 自然 |
暖色渐变 + 不规则色块模拟纸张纹理 + 细微密点 |
二、海报生成
基础用法
use Erikwang2013\Poster\Poster\PosterBuilder; use Erikwang2013\Poster\Drivers\DriverFactory; // 通过辅助函数 $builder = poster_create(750, 1334); // 宽×高 // 或直接实例化 $builder = new PosterBuilder(DriverFactory::create()); $builder->width(750)->height(1334); // 设置背景 $builder->background('#FFFFFF'); // 纯色背景 $builder->background('/path/to/bg.jpg'); // 图片背景(自动缩放) $builder->backgroundGradient('#FF6B6B', '#FF8E53', 'vertical'); // 渐变背景 // 方向: vertical | horizontal // 输出 $builder->save('/output/poster.jpg', 90); // 保存到文件(路径, 质量 0-100) $dataUrl = $builder->output('png', 90); // 获取 base64 data URL
文字 addText()
$builder->addText('新品首发', [ 'x' => 80, // 横坐标 'y' => 120, // 纵坐标(基线位置) 'size' => 48, // 字号 'color' => '#333333', // 颜色 'font' => '/path/to/font.ttf', // 字体文件,null=GD 内置 'align' => 'center', // left | center | right 'maxWidth' => 600, // 最大宽度(自动换行) 'lineHeight' => 72, // 行高 'angle' => 0, // 旋转角度 ]);
图片 addImage()
$builder->addImage('/path/to/product.jpg', [ 'x' => 75, 'y' => 280, 'width' => 600, // 渲染宽度(自动缩放) 'height' => 600, // 渲染高度 'radius' => 12, // 圆角半径 'shadow' => [ // 阴影(可选) 'color' => '#00000033', 'offsetX' => 4, 'offsetY' => 4, 'blur' => 10, ], ]);
头像 addAvatar()
$builder->addAvatar('/path/to/avatar.jpg', [ 'x' => 80, 'y' => 60, 'size' => 120, // 头像尺寸(正方形) 'border' => '#FF6B6B', // 边框颜色(可选) ]);
二维码 addQrcode()
$builder->addQrcode('https://example.com/page/123', [ 'x' => 275, 'y' => 1050, 'size' => 200, // 二维码尺寸 'level' => 'H', // 容错级别 L | M | Q | H 'logo' => '/path/to/logo.png', // 中心 Logo(可选) 'label' => '扫码查看详情', // 底部文案(可选) 'label_size' => 14, 'label_color' => '#999999', ]);
形状 addShape()
// 矩形 $builder->addShape('rect', [ 'x' => 0, 'y' => 0, 'width' => 750, 'height' => 60, 'color' => '#FF6B6B', 'filled' => true, // true=填充 false=描边 'radius' => 8, // 圆角半径 'opacity' => 0.8, // 透明度 0-1 ]); // 圆形 $builder->addShape('circle', [ 'x' => 100, 'y' => 100, 'width' => 80, 'height' => 80, 'color' => '#4ECDC4', ]);
分割线 addLine()
$builder->addLine([ 'x1' => 75, 'y1' => 800, 'x2' => 675, 'y2' => 800, 'color' => '#EEEEEE', 'width' => 1, ]);
水印 addWatermark()
$builder->addWatermark('CONFIDENTIAL', [ 'size' => 24, 'color' => '#00000020', // 半透明 'font' => '/font.ttf', 'angle' => 30, // 倾斜角度 'spacing' => 200, // 间距 ]);
表格 addTable()
$builder->addTable([ 'x' => 50, 'y' => 800, 'width' => 650, 'columns' => [150, 350, 150], // 列宽 'header' => ['序号', '项目', '价格'], 'rows' => [ ['1', '商品A', '¥99'], ['2', '商品B', '¥199'], ['3', '商品C', '¥299'], ], 'headerBg' => '#333333', 'headerColor' => '#FFFFFF', 'rowBg' => ['#FFFFFF', '#F5F5F5'], // 斑马纹 'rowColor' => '#333333', 'fontSize' => 24, 'cellPadding' => 10, ]);
图表 addChart()
// 柱状图 $builder->addChart('bar', [ ['label' => '一月', 'value' => 120], ['label' => '二月', 'value' => 200], ['label' => '三月', 'value' => 150], ['label' => '四月', 'value' => 300], ], [ 'x' => 50, 'y' => 100, 'width' => 650, 'height' => 400, 'colors' => ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'], ]); // 折线图 $builder->addChart('line', [ ['label' => '周一', 'value' => 10], ['label' => '周二', 'value' => 35], ['label' => '周三', 'value' => 25], ['label' => '周四', 'value' => 45], ['label' => '周五', 'value' => 30], ], [ 'x' => 50, 'y' => 100, 'width' => 650, 'height' => 400, 'colors' => ['#FF6B6B'], ]); // 饼图 $builder->addChart('pie', [ ['label' => '电商', 'value' => 45], ['label' => '社交', 'value' => 25], ['label' => '搜索', 'value' => 15], ['label' => '其他', 'value' => 15], ], [ 'x' => 75, 'y' => 100, 'width' => 600, 'height' => 600, 'colors' => ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'], ]);
日历 addCalendar()
$builder->addCalendar([ 'x' => 50, 'y' => 200, 'year' => 2026, 'month' => 5, // 1-12 'cellSize' => 60, // 格子大小 'startDay' => 0, // 0=周日 1=周一 'title' => '2026年5月', // 标题(默认自动生成) 'highlights' => [ // 高亮日期 '2026-05-01' => ['bg' => '#FF6B6B', 'text' => '劳动节'], '2026-05-16' => ['bg' => '#FFEAA7', 'text' => '今天'], ], 'headerBg' => '#333333', // 标题栏背景 'headerColor' => '#FFFFFF', // 标题栏文字颜色 'cellBg' => '#FFFFFF', // 格子背景 'cellBorder' => '#DDDDDD', // 格子边框 'todayBg' => '#FF6B6B', // 今天背景色 'highlightBg' => '#FFF3CD', // 高亮默认背景色 'textColor' => '#333333', // 日期文字颜色 'dimColor' => '#CCCCCC', // 非本月/空白颜色 ]);
艺术字体 addArtisticText()
// 描边效果 $builder->addArtisticText('SALE', 'stroke', [ 'x' => 80, 'y' => 120, 'size' => 72, 'color' => '#FF6B6B', // 填充颜色 'strokeColor' => '#000000', // 描边颜色 'strokeWidth' => 3, // 描边宽度 ]); // 阴影效果 $builder->addArtisticText('新品', 'shadow', [ 'x' => 80, 'y' => 120, 'size' => 48, 'color' => '#333333', 'shadowColor' => '#00000033', 'shadowOffsetX' => 4, 'shadowOffsetY' => 4, ]); // 渐变效果 $builder->addArtisticText('VIP', 'gradient', [ 'x' => 80, 'y' => 120, 'size' => 60, 'color' => '#FF6B6B', // 顶部颜色 'color2' => '#FF8E53', // 底部颜色 ]); // 霓虹发光效果 $builder->addArtisticText('HOT', 'neon', [ 'x' => 80, 'y' => 120, 'size' => 56, 'color' => '#FF1493', 'glowColor' => '#FF1493', ]);
Emoji addEmoji()
// 直接使用 emoji 字符 $builder->addEmoji('😀', ['x' => 100, 'y' => 100, 'size' => 64]); $builder->addEmoji('🎉', ['x' => 180, 'y' => 100, 'size' => 64]); // 使用 unicode 码点 $builder->addEmoji('', [ 'x' => 100, 'y' => 100, 'size' => 64, 'codepoint' => 'U+1F600', // 等同于 😀 ]); // 指定 emoji 字体(需系统支持彩色字体) $builder->addEmoji('😀', [ 'x' => 100, 'y' => 100, 'size' => 64, 'font' => '/System/Library/Fonts/Apple Color Emoji.ttc', ]);
系统会自动检测 macOS / Linux / Windows 上的 emoji 字体路径。
字体图标 addIcon()
// 使用内置 FontAwesome 图标名(需提供图标字体文件) $builder->addIcon('heart', [ 'x' => 20, 'y' => 40, 'size' => 32, 'color' => '#E74C3C', 'font' => '/path/to/fa-solid-900.ttf', // 必须提供 FontAwesome TTF 字体 ]); $builder->addIcon('star', ['x' => 60, 'y' => 40, 'color' => '#F39C12', 'font' => '/path/to/fa-solid-900.ttf']); $builder->addIcon('check', ['x' => 100, 'y' => 40, 'color' => '#27AE60', 'font' => '/path/to/fa-solid-900.ttf']); // 使用自定义 unicode 码点 $builder->addIcon('', [ 'x' => 20, 'y' => 40, 'size' => 32, 'codepoint' => '\\u{F3C5}', // map-marker 'color' => '#E74C3C', 'font' => '/path/to/fa-solid-900.ttf', ]); // 内置图标名列表 // heart, star, user, clock, home, cog, check, times, search, // envelope, phone, camera, play, pause, shopping-cart, tag, // map-marker, calendar, comment, share, download, upload, // lock, globe, link, image, music, video, bell, bookmark, // thumbs-up, eye, trash, edit, plus, minus, arrow-*, // location-dot, fire, gift, rocket
颜文字 addEmoticon()
// 使用内置颜文字 $builder->addEmoticon('happy', ['x' => 20, 'y' => 40, 'size' => 24]); // 渲染: (。•̀ᴗ-)✧ $builder->addEmoticon('love', ['x' => 20, 'y' => 80, 'size' => 24]); // 渲染: (♡°▽°♡) $builder->addEmoticon('cry', ['x' => 20, 'y' => 120, 'size' => 24]); // 渲染: (╥﹏╥) // 自定义表情文字 $builder->addEmoticon('', [ 'x' => 20, 'y' => 40, 'size' => 24, 'text' => '(╯°□°)╯︵ ┻━┻', // 自定义文字 'color' => '#333333', ]); // 内置颜文字表达式 // happy, love, cry, angry, surprised, cool, sleepy, // wave, think, shrug, tableflip, lenny
三、模板系统
use Erikwang2013\Poster\Poster\PosterTemplate; // 定义模板(JSON 可序列化) $template = PosterTemplate::fromConfig([ 'width' => 750, 'height' => 1334, 'elements' => [ ['type' => 'shape', 'color' => '#FF6B6B', 'x' => 0, 'y' => 0, 'width' => 750, 'height' => 300], ['type' => 'text', 'text' => '{{title}}', 'x' => 80, 'y' => 100, 'size' => 48, 'color' => '#FFFFFF'], ['type' => 'text', 'text' => '{{subtitle}}', 'x' => 80, 'y' => 180, 'size' => 28, 'color' => '#FFE0E0'], ['type' => 'image', 'src' => '{{cover}}', 'x' => 75, 'y' => 350, 'width' => 600, 'height' => 600, 'radius' => 12], ['type' => 'qrcode', 'content' => '{{url}}', 'x' => 275, 'y' => 1050, 'size' => 200, 'label' => '扫码查看详情'], ], ]); // 使用模板 + 变量渲染 $builder->useTemplate($template)->with([ 'title' => '新品首发', 'subtitle' => '限时特惠 · 买一送一', 'cover' => '/path/to/product.jpg', 'url' => 'https://m.example.com/product/123', ])->save('/output/poster.jpg'); // 模板支持的元素类型: text, image, qrcode, avatar, shape, line, watermark, table, // chart, calendar, artistic-text, emoji, icon, emoticon
框架集成
Laravel
use Erikwang2013\Poster\Adapters\Laravel\Facades\Captcha; use Erikwang2013\Poster\Adapters\Laravel\Facades\Poster; $result = Captcha::create('click')->generate(); Poster::width(750)->height(1334)->background('#FFF')->save('poster.jpg');
php artisan vendor:publish --tag=poster-config
ThinkPHP
config/web.php:
'services' => [ Erikwang2013\Poster\Adapters\ThinkPHP\CaptchaService::class, Erikwang2013\Poster\Adapters\ThinkPHP\PosterService::class, ],
Webman
config/bootstrap.php:
return [ Erikwang2013\Poster\Adapters\Webman\CaptchaPlugin::class, Erikwang2013\Poster\Adapters\Webman\PosterPlugin::class, ];
Hyperf
通过 ConfigProvider 自动注册。
配置
见 config/poster.php,完整配置项包括图像驱动、验证码(含背景图目录/程序化风格/存储/有效期/容差)、海报生成等。支持 .env 覆盖(参考 .env.example)。
目录结构
src/
├── Captcha/ # 验证码模块
├── Poster/ # 海报模块
│ └── Elements/ # 14 种渲染元素
├── Drivers/ # 图像驱动(GD / ImageMagick)
├── Qrcode/ # 纯 PHP 二维码生成器
├── Storage/ # 验证数据存储(File / Session / Redis)
└── Adapters/ # 框架适配层
开源不易,欢迎支持
| 微信 | 支付宝 |
|---|---|
![]() |
![]() |
License
MIT License — Copyright (c) 2026 erik erik@erik.xyz — https://erik.xyz
erikwang2013/poster-php 适用场景与选型建议
erikwang2013/poster-php 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 321 次下载、GitHub Stars 达 1, 最近一次更新时间为 2026 年 05 月 16 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「image」 「captcha」 「laravel」 「poster」 「thinkphp」 「qr-code」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 erikwang2013/poster-php 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 erikwang2013/poster-php 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 erikwang2013/poster-php 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Yii2 LightBox image galary widget uses Lightbox v2.10.0 by Lokesh Dhakar
Diese Contao 4 Erweiterung stellt Google reCAPTCHA V2 in Form eines neuen Formularfeldes im Formulargenerator bereit. This extension provides Google reCAPTCHA V2 in the form of a new form field in the form generator of Contao Open Source CMS.
The Yii2 extension uses jQuery jquery.carousel-1.1.min.js and makes image carousel from php array of structure defined.
Two Captcha
The Yii2 extension uses jQuery PrettyPhoto and OwlCarousel js and makes image galary from php array of structure defined.
Laravel 5 Securimage helper
统计信息
- 总下载量: 321
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 35
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-16

