Laravel - Seeding Relationships Laravel provides a convenient way to seed database relationships using seeders. Seeders are classes that allow you to populate your database with fake data for testing or development purposes. To seed relationships, you c

10 浏览
0 Comments

Laravel - Seeding Relationships Laravel provides a convenient way to seed database relationships using seeders. Seeders are classes that allow you to populate your database with fake data for testing or development purposes. To seed relationships, you c

在Laravel中,数据库填充通常通过模型工厂来完成。所以你可以使用Faker数据定义你的模型的蓝图,并指定你需要的实例数量:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});
$user = factory(App\User::class, 50)->create();

然而,假设你的User模型与其他多个模型(例如Post模型)具有hasMany关系:

Post:
   id
   name
   body
   user_id

在这种情况下,你希望使用在User表中填充的实际用户填充你的Posts表。虽然这似乎没有明确讨论过,但我在Laravel文档中找到了以下内容:

$users = factory(App\User::class, 3)
    ->create()
    ->each(function($u) {
         $u->posts()->save(factory(App\Post::class)->make());
    });

所以在你的User工厂中,为每个创建的User创建X个Posts。然而,在一个大型应用程序中,可能有50-75个模型与User模型共享关系,那么你的User填充器将最终用其所有关系填充整个数据库。

我的问题是:这是处理这个问题的最佳方式吗?我唯一能想到的另一种方式是首先填充Users(而不填充任何关系),然后在填充其他模型时从数据库中随机选择User。然而,在需要保持唯一性的情况下,你将不得不跟踪哪些User已经被使用过。此外,这似乎会给填充过程增加很多额外的查询负担。

0
0 Comments

在Laravel中,有时需要在seeder中创建具有关联关系的模型。例如,在创建用户模型(User)时,还需要创建帖子模型(Post)。然而,传统的方式在创建模型时无法解决关联关系的问题。

为了解决这个问题,可以使用闭包函数(closures)来在ModelFactory中定义模型的关联关系。通过在Post模型的工厂方法中使用闭包函数来获取用户模型的id,并将其赋值给post模型的user_id属性,从而实现了模型之间的关联关系。

下面是一个示例代码,展示了如何在ModelFactory中定义模型的关联关系:

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});
$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'body' => $faker->paragraph(1),
        'user_id' => function() {
            return factory(App\User::class)->create()->id;
        },
    ];
});

在seeder中,可以简单地使用如下代码来创建10个用户,并为每个用户创建5篇帖子,并传入用户的id:

//创建10个用户
factory(User::class, 10)->create()->each(function ($user) {
    //为每个用户创建5篇帖子
    factory(Post::class, 5)->create(['user_id'=>$user->id]);
});

需要注意的是,通过上述方法创建的模型不会在数据库中产生额外的无关记录,而是在创建关联记录之前先给关联属性赋值。

这种方法被认为是最佳的解决方案,因为它既简洁又优雅。它大大节省了开发者的时间,得到了许多开发者的好评。

另外,近年来在帖子的工厂方法中也可以使用稍微简化的方式来获取用户id,代码如下:

'user_id' => factory(User::class),

不再需要使用闭包函数。

通过上述方法,可以轻松地在Laravel中实现模型之间的关联关系,并且避免了繁琐的手动赋值操作。

0
0 Comments

Laravel中的Seeder用于填充数据库表,以便在开发和测试过程中使用。然而,在填充关联关系时,可能会遇到问题。本文将介绍一个关于Laravel Seeder中关联关系的问题以及解决方法。

在Laravel Seeder中,可以使用saveMany方法来填充关联关系。例如,可以使用以下代码填充用户和帖子的关联关系:

factory(User::class, 10)->create()->each(function ($user) {
    $user->posts()->saveMany(factory(Posts::class, 5)->make());
});

上述代码将创建10个用户,并为每个用户创建5篇帖子。通过saveMany方法,将帖子与用户关联起来。

在上述代码中,可能有人会困惑为什么要使用saveMany方法,而不是使用create方法。saveMany方法的好处是可以一次性保存多个模型,而不需要循环保存每个模型。这样可以提高代码的效率。

另外,有人可能会疑惑新创建的用户的id如何添加到新帖子的user_id字段中。实际上,在使用saveMany方法时,Laravel会自动处理这个问题。当保存多个模型时,Laravel会自动将父模型的id分配给子模型的外键字段。

总之,Laravel Seeder中的关联关系填充问题可以通过使用saveMany方法来解决。这种方法可以一次性保存多个模型,提高代码效率。此外,Laravel还会自动处理父模型id分配给子模型的外键字段的问题。

0
0 Comments

在使用Laravel进行数据填充时,有时候需要填充关联关系的数据。下面是一种将关联关系放在一个seeder类中管理的方法,这样可以将所有逻辑放在一个地方,一目了然。解决方法是创建一个DatabaseSeeder类,并在其中使用私有方法来保持'run'方法的整洁性。以下是一个示例,其中包含了一个User、Link、LinkUser(多对多)和Note(多对一)的关联关系。

多对多关系的解决方法是先创建所有的Links,然后获取插入的id。(由于id是自增的,我认为可以更轻松地获取id(get max),但在这个例子中并不重要)。然后创建用户,并将一些随机的链接附加给每个用户(多对多)。它还为每个用户创建随机的笔记(多对一)。它使用了'factory'方法。

如果你将'Link'替换为你的'Post',这个方法就会起作用。(然后你可以移除'Note'部分......)

(还有一种方法可以确保你有一个有效的用户,可以使用自己的登录凭据。)

create();
        // Fetch the link ids
        $link_ids = App\Link::all('id')->pluck('id')->toArray();
        // Create random users
        factory(App\User::class, 50)->create()->each(function ($user) use ($link_ids) {
            // Example: Many-to-many relations
            $this->attachRandomLinksToUser($user->id, $link_ids);
            // Example: Many-to-one relations
            $this->createNotesForUserId( $user->id );
        });
        // Make sure you have a user to login with (your own email, name and password)
        $this->updateCredentialsForTestLogin('john.com', 'John Doe', 'my-password');
    }
    /**
     *  $user_id
     *  $link_ids
     *  void
     */
    private function attachRandomLinksToUser($user_id, $link_ids)
    {
        $amount = random_int( 0, count($link_ids) ); // The amount of links for this user
        echo "Attach " . $amount . " link(s) to user " . $user_id . "\n";
        if($amount > 0) {
            $keys = (array)array_rand($link_ids, $amount); // Random links
            foreach($keys as $key) {
                DB::table('link_user')->insert([
                    'link_id' => $link_ids[$key],
                    'user_id' => $user_id,
                ]);
            }
        }
    }
    /**
     *  $user_id
     *  void
     */
    private function createNotesForUserId($user_id)
    {
        $amount = random_int(10, 50);
        factory(App\Note::class, $amount)->create([
            'user_id' => $user_id
        ]);
    }
    /**
     *  $email
     *  $name
     *  $password
     *  void
     */
    private function updateCredentialsForTestLogin($email, $name, $password)
    {
        $user = App\User::where('email', $email)->first();
        if(!$user) {
            $user = App\User::find(1);
        }
        $user->name = $name;
        $user->email = $email;
        $user->password = bcrypt($password); // Or whatever you use for password encryption
        $user->save();
    }
}

以上是一个使用Laravel进行关联关系数据填充的解决方法。

0