4. 使用Model Factories快速生成测试数据 - Laravel基础扩展

   2016-12-23 0
核心提示:我们在开发的时候经常会需要修改已经写好的创建表的 migration 文件,但是又不想在开发时就写太多的修改或者添加表字段的 migration 文件,导致 migration 文件过多,而如果直接修改了已经创建好的 migration 文件,那就必须要 migrate:refresh 了,但是表中

我们在开发的时候经常会需要修改已经写好的创建表的 migration 文件,但是又不想在开发时就写太多的修改或者添加表字段的 migration 文件,导致 migration 文件过多,而如果直接修改了已经创建好的 migration 文件,那就必须要 migrate:refresh 了,但是表中的测试数据重新添加又是件麻烦的事,这时候我们就可以使用laravel的数据填充功能 Seeder , 在讨论这个 Seeder 之前,我们先来看下如何批量生成测试数据。

laravel框架默认引入了 fzaninotto/Faker 包,这个包能让我们快速的生成一些测试数据。包的开发思路基于 Perl的Data::Faker和ruby的faker 。这个包的具体使用方式在这里 https://github.com/fzaninotto/Faker ,我们来看下在Laravel中如何使用它.

我们去跑一个Laravel 5.3的框架,并且建立好数据库,并执行掉 php artisan migrate 命令。这里自己做,大家应该是可以闭着眼睛做好这些了。

所有的model factories我们都会放在 database/factories/ModelFactory.php 中,我们打开它:

<?php

/*
| Model Factories 
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
| 你可以在这里定义你所有的模型工厂,使用模型工厂可以让我们在单元测试的时候很方便的使用生成
| 的测试数据,同时也可以快速的将测试数据保存到我们的数据库中。
*/

$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->email,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

默认的已经有了一个为 User 模型生成测试数据的方法,这里的 $faker->name,$faker->unique()->email 都是 fzaninotto/Faker 包提供,上面已经给了它的github地址,大家用的时候自己去查找下就行。

怎么使用它呢? 我们打开 php artisan tinker , 执行

factory(App\User::class)->make();

这句话的意思是,我们会生成一个 User 对象,但是我们会使用模型工厂全局帮助函数 factory() 来生成它,生成的时候就给对象的所有属性赋值。结果如下:

Psy Shell v0.8.0 (PHP 7.0.12 — cli) by Justin Hileman
>>> factory(App\User::class)->make();
=> App\User {#692
     name: "Candace Bins",
     email: "morar.ethan@gmail.com",
   }
>>> factory(App\User::class)->make();
=> App\User {#698
     name: "Prof. Alf Graham MD",
     email: "mpagac@yahoo.com",
   }

每调用一次都会生成一个具有不同属性值的对象,那如果我们要同时生成多个这样的对象呢?比如我们要生成500个 User 对象,我们只要传入第2个参数即可,如下:

factory(App\User::class, 500)->make();

通常我们会需要将这些生成的数据保存到数据库,那使用 create() 即可

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

不过我们一般就不跑到 tinker 中去生成这样测试数据了,我们将这条语句些到 seeds/DatabaseSeeder.phprun 方法中:

public function run()
    {
        // 清空users表中已经存在的数据
        User::truncate();

        factory(User::class, 2)->create();
    }

然后执行:

php artisan db:seed

就会调用上面这个 run() 方法,执行当中的语句了。

不过在正式开发的时候,$faker数据要依据你的具体情况来用了,比如我们会需要一些真实的数据,比如说一些字典表,那必须是正确的数据,那就会手动指定了,所以通常我们对应每个模型都会去写一个 Seeder 类,然后在 DatabaseSeeder.php 中去调用它们,在具体的 Seeder 类中去调用模型工厂,这样代码会方便管理很多,因为现在还没有讲到 Seeder 类,所以我们现在知道怎么用模型工厂就可以了。

对于模型工厂的数据,我们可能更多的还是用在测试中的(测试以后最后再详说),我们看下测试中怎么用:

我们去建立一个 posts 表, migration 文件如下:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->timestamps();
        });
    }

比如我们要测试这个流程: 当我访问post的路由的时候,给我显示数据库中的post的标题和内容.

我们直接改下 tests/ExampleTest.php 中的代码:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Post;

class ExampleTest extends TestCase
{
    // 不让测试的数据保存到数据库中,没有这条语句,当执行phpunit时,会
    // 在posts表中不断的插入数据,自己测试下
    use DatabaseTransactions;
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        // 通过模型工厂生成带有测试数据属性的$post对象
        $post = factory(Post::class)->create();

        $this->visit('posts')
             ->see($post->title);
    }
}

database/factories/ModelFactory.php 中定义模型工厂:

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'title' => $faker->sentence,
        'body' => $faker->paragraph
    ];
});

编写路由文件,laravel 5.3路由分的很细,有针对api的,针对web的,还有针对命令行的,针对web的在 routes/web.php 中( 路由这样改个人觉得很好,比5.2好多了)

Route::get('posts', function() {
  return view('posts')->with('posts', App\Post::all());
});

然后去弄个 resources/views/posts.blade.php 视图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>zhoujiping.com</title>
</head>
<body>
    @foreach ($posts as $post)
        <article>
            <h2>{{ $post->title }}</h2>
            <div class="body">{{ $post->body }}</div>
        </article>
    @endforeach
</body>
</html>

到命令行执行 phpunit , 是绿色的 4. 使用Model Factories快速生成测试数据 - Laravel基础扩展

我们在回头来说下 fzaninotto/Faker 包, 默认我们生成的测试数据都是英文的,如果你一定要想生成中文的测试数据(其实没啥用),该怎么生成?回到 database/factories/ModelFactory.php

fzaninotto/Faker 源码中我们可以看见 fzaninotto/Faker 的包中的关于语言版本相关的都放在Provider中:

4. 使用Model Factories快速生成测试数据 - Laravel基础扩展

而在laravel中$faker是 Faker\Generator 的是一个实例,在 Faker\Generator 中有这样一个方法:

public function addProvider($provider)
    {
        array_unshift($this->providers, $provider);
    }

这样一看就明白了,将需要的语言文件依赖注入进来就可以了。

那我们来改下代码:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    $faker->addProvider(new Faker\Provider\zh_CN\Person($faker));

    static $password;

    return [
        'name' => $faker->name,
        'email' => $faker->unique()->email,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

我们到tinker中跑一下:

4. 使用Model Factories快速生成测试数据 - Laravel基础扩展

现在生成的姓名就是中文的了,但是该组件对中文的支持类太少,所以你可能会在写 Seeder 的时候用一部分$faker,用一部分手动指定,或者自己写一些数组,随机插入也可以。

本节到这里结束。

 
标签: Laravel 数据库
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • nginx 各类网站设置 (laravel , thinkphp , nod
    基础部分设置[root@centos ~]# vim /opt/nginx/conf/nginx.confuser www www;worker_processes auto;pid logs/nginx.pid;worker_rlimit_nofile 100000;events {use epoll;multi_accept on;worker_connections 65535 ;}http {include mime.types;default_type
    02-09
  • PHP trait 特性在 Laravel 中的使用个人心得
    trait 是在PHP5.4中为了方便代码复用的一种实现方式,但目前我在看的的PHP项目中较少看的有程序员去主动使用这个实现方式,在laravel中有很多 trait 的使用,关于trait 在 laravel 的使用请参看 Laravel 在哪些地方用了 trait?我曾在 Laravel 中大型项目面向
    02-09
  • 让我们用 laravel-mix 为 TypeScript 和 Sass
    介绍前端编译TypeScript、Sass、模板引擎等时经常用到Gulp和webpack。这是我个人的印象,但它们似乎都难以管理,因为它们的描述往往复杂而冗长。我不想积极进行,因为我要担心加载器的顺序并且有很多配置选项,我必须花时间去了解它们。我想推荐那里laravel
  • PHP Laravel软删除的实现方法介绍
    用Laravel 自带的 Eloquent ORM 来实现软删除。首先在数据迁移文件中添加删除时间字段./database/migrations/2014_10_12_000000_create_users_table.php?phpuse Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illu
  • Laravel中如何使用PHP的装饰器模式 php laravel
    本文小编为大家详细介绍“Laravel中如何使用PHP的装饰器模式”,内容详细,步骤清晰,细节处理妥当,希望这篇“Laravel中如何使用PHP的装饰器模式”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。装饰器模式定义:它可以帮助您在
    02-08 laravelphp
  • PHP laravel使用自定义邮件类实现发送邮件
    PHP laravel使用自定义邮件类实现发送邮件
    当登录邮箱为腾讯企业邮箱的时候。Phpmailer发送邮件就不好用了,具体哪里不好用,我没真没找到。但是,邮件得发啊,怎么办呢?我这里搞了一个自定义的发送邮件类,腾讯企业邮箱也可用。但是,邮件发送失败,不会返回报错信息,这个可能是有点坑。源码如下:?
  • 详解PHP laravel中的加密与解密函数
    目录一:简介二:配置三:使用加密/解密1:加密2:不使用序列化进行加密3:解密Laravel为我们提供了完整的加密方法及加密模式。我之前一般在加密的时候使用的是我自己写的加密函数,但是这个玩意,有的位置还是不太使用,当然,破解的话,基本上也是不可能的
  • PHP laravel缓存cache机制详解
    目录一、访问多个缓存存储二、从缓存中获取数据1.获取数据并设置默认值2.检查缓存项是否存在3.数值增加/减少4.获取存储5.获取删除三、缓存中存储数据1.获取存储数据2.缓存不存在时存储数据3.永久存储数据四、从缓存中移除数据Laravel中的cache为我们提供了三
  • PHP laravel实现导出PDF功能
    PHP laravel实现导出PDF功能
    目录一、laravel-tcpdf二、tcpdf三、TCPDF解决保存中文文件名的方法补充一、laravel-tcpdf导出PDF文件Laravel框架为我们集成了一个插件tcpdf。下载地址:https://github.com/elibyy/tcpdf-laravel然后使用composer进行安装就可以了。具体安装过程,请查看文末
  • PHP laravel缓存cache机制怎么实现
    今天小编给大家分享一下PHP laravel缓存cache机制怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Laravel中的cache为我们
点击排行