【问题标题】:Seeding database with random states in LaravelLaravel 中随机状态的种子数据库
【发布时间】:2020-10-23 09:54:35
【问题描述】:

我有一个 Laravel 8 应用程序,我希望能够在执行 php artisan db:seed 时为我的一张表设置不同的状态。这是一个示例表:

Create Table: CREATE TABLE `notifications` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `message` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `is_read` tinyint(1) NOT NULL DEFAULT '0',
  `recipient_role` enum('Manager','Employee') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'Manager',
  `recipient_id` bigint(20) unsigned NOT NULL,
  `sender_id` bigint(20) unsigned NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `notifications_recipient_id_foreign` (`recipient_id`),
  KEY `notifications_sender_id_foreign` (`sender_id`),
  CONSTRAINT `notifications_recipient_id_foreign` FOREIGN KEY (`recipient_id`) REFERENCES `users` (`id`),
  CONSTRAINT `notifications_sender_id_foreign` FOREIGN KEY (`sender_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

在这种特殊情况下,我想使用Notification::factory 创建多个Notification 实例,其中is_read 随机设置为10。我还想确保为recipient_idsender_id 选择了两个随机的User 实例(它们将首先播种)。这意味着我不能将它们硬编码到我的工厂中。

在实际工厂中我只填写了message

<?php

namespace Database\Factories;

use App\Models\Notification;
use Illuminate\Database\Eloquent\Factories\Factory;

class NotificationFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Notification::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            //
            'message' => $this->faker->sentence,
            
        ];
    }
}

我的问题是,在NotificationSeeder.php 定义中,如何确保我有一个随机的is_read 状态以及分配给recipient_idsender_id 的两个不同用户?

【问题讨论】:

    标签: php laravel eloquent


    【解决方案1】:

    我没有使用 Laravel 8 的经验,但我认为它应该可以工作:

    通知工厂:

    public function definition()
    {
        // Get 2 random users IDs
        $users = User::inRandomOrder()->take(2)->pluck('id');
    
        return [
            'message'      => $this->faker->sentence,
            'is_read'      => rand(0, 1),
            'recipient_id' => $users->first(),
            'sender_id'    => $users->last(),
        ];
    }
    

    如果您先创建用户,则只需获得 2 个随机用户。我打了 1 个电话来获得 2 个用户,而不是每个用户打 1​​ 个电话。这将返回一组用户 ID,将第一个用于“recipient_id”,将最后一个用于“sender_id”。

    【讨论】:

      【解决方案2】:

      使用faker的numberBetween函数得到一个0-1之间的随机数。 https://github.com/fzaninotto/Faker#fakerproviderbase

      <?php
      
      namespace Database\Factories;
      
      use App\Models\Notification;
      use Illuminate\Database\Eloquent\Factories\Factory;
      
      class NotificationFactory extends Factory
      {
          /**
           * The name of the factory's corresponding model.
           *
           * @var string
           */
          protected $model = Notification::class;
      
          /**
           * Define the model's default state.
           *
           * @return array
           */
          public function definition()
          {
              return [
                  //
                  'message' => $this->faker->sentence,
                  'is_read' => $this->faker->numberBetween(0, 1),
                  
              ];
          }
      }
      

      然后,当您创建通知时,首先创建您的用户,然后将它们提供给 make/create 方法。

      // create two users
      $first = User::factory()->count(1)->create();
      $second = User::factory()->count(1)->create();
      
      // override the default notification attributes with the user's id
      $notification = Notification::factory()->count(1)->create([
              'recipient_id' => $first->id,
              'sender_id' => $second->id,
      ]);
      

      【讨论】:

      • 即使我已经在之前的种子类中为数据库播种了,但正如您在通知播种器中所做的那样,重新创建用户是否是一种更好的做法?
      • @randombits 我不知道您正在播种的数据量,但请进行测试,看看这两种方法之间是否有任何区别。只要有可能,我宁愿不要从其他播种机重新播种表。只是为了跟踪哪个人在做什么。
      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 2018-08-18
      • 2015-02-04
      • 2016-02-04
      • 2013-05-28
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多