Loading [MathJax]/jax/output/CommonHTML/fonts/TeX/AMS-Regular.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >通过填充器快速填充 Laravel 测试数据

通过填充器快速填充 Laravel 测试数据

作者头像
学院君
发布于 2021-01-22 02:58:38
发布于 2021-01-22 02:58:38
10.2K00
代码可运行
举报
文章被收录于专栏:学院君的专栏学院君的专栏
运行总次数:0
代码可运行

我们在前两篇教程中分别介绍了如何连接到数据库,以及如何通过迁移文件定义表结构来创建或修改数据表,接下来,是时候在数据表里添加内容了。在 Laravel 框架中,如果想要快速填充测试数据到数据库,可以借助框架提供的填充器功能,通过填充器,我们可以非常方便地为不同数据表快速填充测试数据。

填充器简介

在应用根目录的 database/seeds 目录下,默认包含一个 DatabaseSeeder.php 文件。这就是 Laravel 自带的一个填充器示例文件,该填充器类提供了一个 run 方法,当我们运行填充命令时,就会调用该方法执行数据库填充。

填充器的运行

Laravel 提供了两种方式来运行填充器:一种是独立的填充命令,另一种是在运行迁移命令时通过指定标识选项在创建数据表时填充。

独立的填充命令如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
php artisan db:seed
php artisan db:seed --class=UsersTableSeeder

上述第一个 Artisan 命令会以 DatabaseSeeder 为入口类,调用该类的 run 方法,你可以将所有对其他填充器的调用定义在该方法中,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$this->call(UsersTableSeeder::class);

这样,就可以一次性调用所有填充器啦。

当然,你也可以通过 --class= 选项指定运行某个填充器类的 run 方法。

此外,在某些时候,你可能希望在运行迁移命令的同时填充测试数据,尤其是在初始化一些演示项目的时候。这可以通过不指定值的 --seed 选项来实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
php artisan migrate --seed 
php artisan migrate:refresh --seed

第一条命令用于执行迁移命令时运行填充器类 DatabaseSeeder 填充数据,第二条命令用于回滚所有迁移并重新运行迁移同时填充初始化数据。

编写填充器类

介绍完如何运行填充器,是时候来编写第一个填充器类了。我们可以通过如下 Artisan 命令为 users 表快速创建一个填充器类 UsersTableSeeder

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
php artisan make:seeder UsersTableSeeder

该命令会在 database/seeds 目录下创建一个 UsersTableSeeder 填充器类,初始化代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

use Illuminate\Database\Seeder;

class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {

    }
}

我们可以将填充逻辑编写到 run 方法里:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public function run()
{
    DB::table('users')->insert([
        'name' => str_random(10),
        'email' => str_random(10).'@gmail.com',
        'password' => bcrypt('secret'),
    ]);
}

这里我们借助了查询构建器(下一篇教程将介绍)来插入数据,指定用户名和邮箱为长度不大于10的随机字符串,邮箱后缀是 @gmail.com,密码是对 secret 字符串进行加密后的字符串。

这样,我们就编写好了第一个填充器类,接下来,我们可以通过指定填充器类的方式将这条记录插入到数据库:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
php artisan db:seed --class=UsersTableSeeder

你还可以在 DatabaseSeeder 类的 run 方法中运行这个填充器类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public function run()
{
    $this->call(UsersTableSeeder::class);
}

如果有多个填充器类,想要一次性运行,可以将它们都放到这个方法中调用。然后运行如下 Artisan 命令即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
php artisan db:seed

这样,就可以在数据表 users 中看到新填充的用户记录了:

当然,我们可以在 UsersTableSeeder 类中定义多条插入语句来一次性插入多条记录。

通过模型工厂填充数据

以上编写填充器类填充数据到数据库虽然已经很方便了,但是每次插入一条记录都要编写一条语句或者手动指定插入数据,如果需要填充的测试数据有成千上万条,那不是要崩溃掉。有没有一种机制可以支持一次定义,多次填充呢?为了解决这个问题,我们需要引入一种模式,一次定义填充规则,在每次具体运行时,通过指定填充次数来决定填充多少条记录。模型工厂的概念应运而生:我们在一个 Eloquent 模型类(后面马上会讲到)上定义一个工厂方法,通过指定规则批量插入填充数据。

你可以想象,有了模型工厂的加持,会为我们日后测试带来多大的便利。现在,我们先抛开测试不谈,赶紧来看下如何在 Laravel 中定义模型工厂。

创建模型工厂

模型工厂位于 database/factories 目录下,Laravel 自带了一个用于填充 User 模型的模型工厂 UserFactory.php

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?php

use Faker\Generator as Faker;

/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/

$factory->define(App\User::class, function (Faker $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'email_verified_at' => now(),
        'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
        'remember_token' => str_random(10),
    ];
});

注:在 Laravel 6.0 中,请使用 \Illuminate\Support\Str::random(10) 替代 str_random(10) 调用。

在模型工厂文件中,我们通过 factory>defineUserFakerFaker使

调用模型工厂

在调用这些模型工厂的时候,需要借助 Laravel 提供的全局辅助函数 factory(),比如我们在 UsersTableSeederrun 方法中通过模型工厂改写数据填充方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public function run()
{
    /*DB::table('users')->insert([
        'name' => str_random(10),
        'email' => str_random(10).'@gmail.com',
        'password' => bcrypt('secret'),
    ]);*/

    factory(\App\User::class, 5)->create();
}

我们将之前手动编写填写数据的方式注释起来,替换成新的模型工厂的方式,代码瞬间简洁了很多,由于我们在 UserFactory.php 中全局定义了 User 模型的模型工厂,所以在这里只需调用 factory 方法,传入对应模型类和要填充的记录数即可,最后再调用 create 方法让变更生效。非常方便,也真正实现了一次定义,多处复用,以及在运行时指定填充记录数。

运行填充器的方式还是和填充器类中介绍的一样。比如我们还是通过运行 php artisan db:seed 命令来填充数据到数据库,此时,就可以看到新填充了 5 条记录:

注:本教程都以 Laravel 自带的 users 及对应 User 模型类为例进行演示,对于其他数据表和对应模型类,依样画葫芦就好。

本系列教程首发在Laravel学院(laravelacademy.org),你可以点击页面左下角阅读原文链接查看最新更新的教程。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客书房 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JAVA多线程详解
分为两种:一类是守护线程,典型是垃圾回收GC;第二类是用户线程,当JVM中都是JVM守护线程,那么当前的JVM将退出。
阮键
2019/08/07
4320
十五、多线程【黑马JavaSE笔记】
假如计算机只有一个CPU,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的
啵啵鱼
2022/11/23
2900
十五、多线程【黑马JavaSE笔记】
Java之多线程-------入门
是指从软件或者硬件上实现多个线程并发执行的技术。 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能。
楠羽
2022/11/18
3760
Java之多线程-------入门
Java 线程与多线程
一个进程上可以创建多个线程,线程比进程更快的处理单元,而且所占用的资源也小,多线程的应用也是性能最高的。
Mirror王宇阳
2020/11/12
1.9K0
java线程详解(史上最全)
根据本人多年从业以及学习经验,录制了一套最新的Java精讲视频教程,如果你现在也在学习Java,在入门学习Java的过程当中缺乏系统的学习教程,你可以加QQ群654631948领取下学习资料,面试题,开发工具等,群里有资深java老师做答疑,每天也会有基础部分及架构的直播课,也可以加我的微信renlliang2013做深入沟通,只要是真心想学习Java的人都欢迎。
全栈程序员站长
2022/09/08
2690
java线程详解(史上最全)
多线程详解
假如计算机只有一个CPU,那么CPU在某一时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性的。
秋落雨微凉
2022/10/25
4510
多线程
线程类 Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例 每个线程的作用是 完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码 Java使用线程执行体来代表这段程序流。
JokerDJ
2023/11/27
1950
多线程
JUC 多线程基础
如果一个线程对共享变量的修改,能够被其它线程看到,那么就能说明共享变量在线程之间是可见的。如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。
万能青年
2019/08/30
5300
JUC 多线程基础
第二十四天 多线程-多线程&线程安全【悟空教程】
进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。
Java帮帮
2018/07/26
6540
第二十四天 多线程-多线程&线程安全【悟空教程】
Java多线程(全知识点)
概述:本文为Java多线程的基础知识点的第一部分,主要包括,通过继承Thread来实现进程,线程调度,线程控制,run(),start(),join(),sleep(),setDaemon()方法的使用,获取线程名字currentThread(),线程同步,非静态锁,静态方法的锁,Lock锁,生产者与消费者问题,卖票问题。
GeekLiHua
2025/01/21
1410
Java多线程(全知识点)
Java 多线程之 Runnable VS Thread 及其资源共享问题
对于 Java 多线程编程中的 implements Runnable 与 extends Thread,部分同学可能会比较疑惑,它们之间究竟有啥区别和联系呢?他们是不是没啥区别随便选呢?实际中究竟该
用户1177713
2018/02/24
9200
Java 多线程之 Runnable VS Thread 及其资源共享问题
第二十五天 多线程-常用方法&线程池【悟空教程】
System.out.println(getName() + " ==== " + i );
Java帮帮
2018/07/26
3900
第二十五天 多线程-常用方法&线程池【悟空教程】
java_线程、同步、线程池
Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例
咕咕星
2020/08/19
8570
java_线程、同步、线程池
Java-多线程(下)
    线程的同步与死锁是多线程里面最需要重点理解的概念。这种操作的核心问题在于:每一个线程对象轮番强占资源
Java架构师必看
2021/11/11
2500
day18-多线程&线程同步&死锁
在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。
张哥编程
2024/12/13
900
java基础第十六篇之多线程
1:线程的概念 进程(任务):一个正在运行的程序 进程的调度:CPU来决定什么时候该运行哪个进程 (时间片轮流法) 线程在一个应用程序中,同时,有多个不同的执行路径,是进程中的实际运作单位。 好处是提高程序效率。
海仔
2019/08/05
2900
Android多线程:继承Thread类、实现Runnable接口使用教程(含实例讲解)
前言 在Android开发中,多线程的使用十分常见 今天,我将全面解析多线程中最常见的2种用法:继承Thread类 & 实现Runnable接口 Carson带你学多线程系列 基础汇总 Android多线程:基础知识汇总 基础使用 Android多线程:继承Thread类使用(含实例教程) Android多线程:实现Runnable接口使用(含实例教程) 复合使用 Android多线程:AsyncTask使用教程(含实例讲解) Android多线程:AsyncTask的原理及源码分析 A
Carson.Ho
2022/03/25
8290
Android多线程:继承Thread类、实现Runnable接口使用教程(含实例讲解)
【19】JAVASE-多线程专题【从零开始学JAVA】
Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。
用户4919348
2024/05/25
1350
【19】JAVASE-多线程专题【从零开始学JAVA】
Java多线程总结(超详细总结)
— JDK 5.0新增 如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大? 1. call()可以有返回值的。 2. call()可以抛出异常,被外面的操作捕获,获取异常的信息 3. Callable是支持泛型的
小尘要自信
2023/10/10
3140
Java学习笔记之多线程 生产者 消费者
        所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
Jetpropelledsnake21
2022/03/07
6050
Java学习笔记之多线程 生产者 消费者
相关推荐
JAVA多线程详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验