FakerPHP/Faker 是 PHP 生态最流行的假数据生成库,是原fzaninotto/faker的官方维护分支(原包已停止更新)。它可以快速生成逼真的测试数据,完美适配单元测试、开发演示数据、数据库填充、压力测试等场景,支持全球几十种语言本地化,对中文环境有完整支持。
一、安装与环境要求
环境要求
- 最新稳定版要求 PHP 7.4 及以上(支持 PHP 8.0+)
- 必须通过 Composer 安装
- 低 PHP 版本兼容:PHP 7.2-7.3 可安装
fakerphp/faker:^1.17
安装命令
开发环境安装(推荐)
Faker 仅用于开发 / 测试场景,推荐安装到开发依赖中,生产环境不会自动加载:
composer require --dev fakerphp/faker
旧包迁移
如果你的项目之前使用已停止维护的fzaninotto/faker,先卸载旧包再安装新包,两者命名空间、API 完全兼容,业务代码无需修改:
composer remove fzaninotto/faker
composer require --dev fakerphp/faker
二、基础使用
核心初始化
<?php
// 引入Composer自动加载
require_once __DIR__ . '/vendor/autoload.php';
// 1. 默认英文环境实例化
// $faker = Faker\Factory::create();
// 2. 简体中文环境实例化(国内用户必用,生成中文数据)
$faker = Faker\Factory::create('zh_CN');
// 3. 繁体中文环境
// $faker = Faker\Factory::create('zh_TW');
// 生成基础假数据
echo $faker->name(); // 输出中文姓名,如 "张伟"
echo $faker->phoneNumber(); // 输出国内手机号,如 "13812345678"
echo $faker->address(); // 输出中文完整地址
?>
固定随机种子(可重复生成相同数据)
通过seed()设置随机数种子,每次运行都会生成完全相同的假数据,适合单元测试保证结果可复现:
$faker = Faker\Factory::create('zh_CN');
// 设置固定种子
$faker->seed(12345);
// 每次运行都会输出相同的姓名
echo $faker->name();
三、核心格式化器(Formatters)分类详解
格式化器是 Faker 生成假数据的核心方法,按使用场景分类如下,重点标注中文环境专属支持的方法:
个人信息类(最常用)
| 方法 | 作用 | 示例输出 |
|---|---|---|
name() | 生成完整中文姓名 | 李娜、王强 |
firstName() | 生成中文名 | 伟、芳 |
lastName() | 生成中文姓 | 张、刘 |
title() | 生成称呼 / 头衔 | 先生、女士、博士、工程师 |
gender() | 生成性别 | 男、女 |
idNumber() | 【zh_CN 专属】生成合法 18 位身份证号 | 110101199001011234 |
age($min=0, $max=100) | 生成指定范围的年龄 | 28 |
birthday($max='now', $format='Y-m-d') | 生成生日 | 1995-03-15 |
licensePlate() | 【zh_CN 专属】生成车牌号 | 京 A12345 |
示例
// 生成完整个人信息
echo "姓名:" . $faker->name() . "\n";
echo "身份证号:" . $faker->idNumber() . "\n";
echo "性别:" . $faker->gender() . "\n";
echo "生日:" . $faker->birthday() . "\n";
地址类
| 方法 | 作用 | 示例输出 |
|---|---|---|
address() | 生成完整中文地址 | 上海市浦东新区张江高科技园区博云路 2 号 |
province() | 【zh_CN 专属】生成省份 | 广东省、四川省 |
city() | 【zh_CN 专属】生成城市 | 深圳市、成都市 |
district() | 【zh_CN 专属】生成区县 | 天河区、武侯区 |
streetAddress() | 生成详细街道地址 | 中关村大街 1 号 |
postcode() | 生成邮政编码 | 100080 |
latitude() / longitude() | 生成经纬度 | 39.9042, 116.4074 |
通讯与互联网类
| 方法 | 作用 | 示例输出 |
|---|---|---|
phoneNumber() | 【zh_CN 专属】生成国内手机号 | 13912345678 |
telNumber() | 【zh_CN 专属】生成固定电话 | 010-87654321 |
email() | 生成邮箱地址 | zhangwei@example.com |
safeEmail() | 生成安全测试邮箱(不会真实发送) | li.na@example.org |
freeEmail() | 生成免费邮箱 | wangqiang@163.com |
username() | 生成用户名 | zhangwei1995 |
url() | 生成随机 URL | https://www.example.com |
domainName() | 生成域名 | example.com |
ipv4() / ipv6() | 生成 IP 地址 | 192.168.1.100 |
userAgent() | 生成浏览器 UA | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36… |
文本与内容类
| 方法 | 作用 |
|---|---|
sentence($nbWords=6) | 生成一句话 |
paragraph($nbSentences=3) | 生成一个段落 |
realText($maxNbChars=200) | 【推荐】基于真实中文语料生成逼真文本,比 text () 更自然 |
word() / words($nb=3) | 生成单个词 / 多个词 |
randomHtml() | 生成随机 HTML 片段 |
日期与时间类
| 方法 | 作用 |
|---|---|
date($format='Y-m-d', $max='now') | 生成指定格式的日期 |
time($format='H:i:s') | 生成时间 |
dateTime($max='now') | 生成 DateTime 对象 |
dateTimeBetween($startDate, $endDate) | 生成指定区间的日期时间,最常用 |
dateTimeInInterval($startDate, $interval) | 生成指定间隔内的日期 |
unixTime() | 生成 Unix 时间戳 |
示例
// 生成最近1年的日期
echo $faker->dateTimeBetween('-1 year', 'now')->format('Y-m-d H:i:s');
// 生成未来30天的日期
echo $faker->dateTimeBetween('now', '+30 days')->format('Y-m-d');
数字与计算类
| 方法 | 作用 |
|---|---|
numberBetween($min, $max) | 生成指定范围的整数 |
randomFloat($nbMaxDecimals, $min, $max) | 生成指定小数位数的浮点数(适合价格、金额) |
boolean($chanceOfGettingTrue=50) | 生成布尔值,可指定为 true 的概率 |
randomDigit() | 生成 0-9 的随机数字 |
randomNumber($nbDigits) | 生成指定位数的随机数 |
示例
// 生成商品价格,0.01-999.99元,两位小数
echo $faker->randomFloat(2, 0.01, 999.99);
// 80%概率为true(模拟已发布状态)
echo $faker->boolean(80);
金融与支付类
| 方法 | 作用 |
|---|---|
bank() | 【zh_CN 专属】生成国内银行名称 |
creditCardNumber() | 生成信用卡号 |
creditCardExpirationDate() | 生成信用卡有效期 |
iban() | 生成国际银行账号 |
图片与文件类
| 方法 | 作用 |
|---|---|
imageUrl($width, $height, $category) | 生成占位图片 URL(基于 picsum.photos,无需下载) |
image($dir, $width, $height) | 生成并下载占位图片到本地(需要网络连接) |
mimeType() | 生成 MIME 类型 |
fileExtension() | 生成文件扩展名 |
其他常用方法
| 方法 | 作用 |
|---|---|
uuid() | 生成 UUID |
hexColor() / rgbCssColor() | 生成颜色值 |
randomElement($array) | 从数组中随机抽取一个元素 |
randomElements($array, $count) | 从数组中随机抽取多个元素 |
shuffle($array/$string) | 打乱数组 / 字符串 |
lexify($pattern) | 替换?为随机字母,如lexify('???')生成 3 位随机字母 |
numerify($pattern) | 替换#为随机数字,如numerify('####')生成 4 位随机数字 |
四、高级修饰符(Modifiers)
修饰符可以链式调用,给格式化器增加额外的规则,是提升开发效率的核心功能,常用的有 3 个:
unique():生成唯一不重复的数据
避免生成重复数据,解决数据库唯一键冲突问题,适合生成唯一邮箱、身份证号、手机号等。
// 生成10个不重复的邮箱
for ($i=0; $i<10; $i++) {
echo $faker->unique()->email() . "\n";
}
// 生成不重复的身份证号
echo $faker->unique()->idNumber();
// 重置唯一性检查
$faker->unique($reset = true);
⚠️ 注意:如果生成数量超过该字段的可能范围,会抛出OverflowException异常,比如生成 100 个不重复的 0-9 的数字,需确保范围足够。
optional():生成可选数据(可空)
模拟非必填字段,有指定概率返回有效值,否则返回默认值(默认 null)。
// 50%概率返回地址,50%返回null
echo $faker->optional()->address();
// 30%概率返回手机号,70%返回null
echo $faker->optional($weight = 0.3)->phoneNumber();
// 自定义默认值,70%概率返回公司名,30%返回"无"
echo $faker->optional($weight = 0.7, $default = '无')->company();
valid():通过自定义规则过滤数据
通过回调函数验证,仅返回符合规则的数据,不满足则重新生成。
// 生成大于100的偶数
$faker->valid(function($value) {
return $value > 100 && $value % 2 == 0;
})->numberBetween(1, 200);
// 生成仅以.com结尾的邮箱
$faker->valid(function($email) {
return str_ends_with($email, '.com');
})->email();
默认最多重试 10000 次,可通过第二个参数自定义最大重试次数:valid($callback, $maxRetries = 20000)。
五、自定义格式化器(自定义 Provider)
当默认格式化器无法满足需求时,可以自定义 Provider 扩展功能,比如生成订单号、商品 SKU、自定义分类等。
实现步骤
- 创建自定义 Provider 类,继承
Faker\Provider\Base - 在类中添加自定义方法(方法名即为格式化器名称)
- 将自定义 Provider 注册到 Faker 实例
- 像使用默认格式化器一样调用
完整示例
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Faker\Factory;
use Faker\Provider\Base;
// 自定义Provider
class CustomProvider extends Base
{
/**
* 生成订单号:ORDER + 年月日 + 6位随机数
*/
public function orderNo()
{
return 'ORDER' . date('Ymd') . $this->generator->randomNumber(6, true);
}
/**
* 生成商品SKU
*/
public function productSku()
{
return strtoupper($this->generator->lexify('???')) . '-' . $this->generator->randomNumber(4, true);
}
/**
* 生成商品分类
*/
public function productCategory()
{
$categories = ['电子产品', '服装鞋帽', '食品生鲜', '家居用品', '美妆护肤', '运动户外'];
return $this->randomElement($categories);
}
}
// 实例化Faker
$faker = Factory::create('zh_CN');
// 注册自定义Provider
$faker->addProvider(new CustomProvider($faker));
// 使用自定义格式化器
echo "订单号:" . $faker->orderNo() . "\n";
echo "商品SKU:" . $faker->productSku() . "\n";
echo "商品分类:" . $faker->productCategory() . "\n";
?>
六、主流框架实战场景
场景 1:Laravel 模型工厂(内置支持)
Laravel 已内置 Faker,无需单独安装,是 Laravel 数据填充的标准方案。
步骤 1:配置中文环境
修改config/app.php,设置 Faker 本地化:
'faker_locale' => 'zh_CN',
步骤 2:创建模型工厂
示例:database/factories/ArticleFactory.php
<?php
namespace Database\Factories;
use App\Models\Article;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class ArticleFactory extends Factory
{
protected $model = Article::class;
public function definition()
{
$title = $this->faker->sentence(5);
return [
'title' => $title,
'slug' => Str::slug($title),
'content' => $this->faker->realText(2000),
'user_id' => $this->faker->numberBetween(1, 10),
'cate_id' => $this->faker->numberBetween(1, 5),
'is_published' => $this->faker->boolean(80), // 80%概率已发布
'published_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
'view_count' => $this->faker->numberBetween(0, 10000),
];
}
}
步骤 3:创建数据填充类
示例:database/seeders/ArticleSeeder.php
<?php
namespace Database\Seeders;
use App\Models\Article;
use Illuminate\Database\Seeder;
class ArticleSeeder extends Seeder
{
public function run()
{
// 批量生成100篇文章
Article::factory()->count(100)->create();
}
}
步骤 4:执行填充
# 执行指定填充器
php artisan db:seed --class=ArticleSeeder
# 执行所有填充器
php artisan db:seed
场景 2:ThinkPHP 6/8 数据填充
步骤 1:安装 Faker
composer require --dev fakerphp/faker
步骤 2:创建填充类
示例:app/seeder/ArticleSeeder.php
<?php
namespace app\seeder;
use think\migration\Seeder;
use Faker\Factory;
use app\model\Article;
class ArticleSeeder extends Seeder
{
public function run()
{
$faker = Factory::create('zh_CN');
$data = [];
// 生成50条数据
for ($i=0; $i<50; $i++) {
$data[] = [
'title' => $faker->sentence(5),
'content' => $faker->realText(1000),
'user_id' => $faker->numberBetween(1, 5),
'cate_id' => $faker->numberBetween(1, 4),
'status' => $faker->boolean(70),
'create_time' => $faker->dateTimeBetween('-6 months', 'now')->format('Y-m-d H:i:s'),
'update_time' => $faker->dateTimeBetween('-3 months', 'now')->format('Y-m-d H:i:s'),
];
}
// 批量插入
Article::insertAll($data);
}
}
步骤 3:执行填充
php think seed:run ArticleSeeder