Laravel:使用模型工厂生成一对多关系

8
我在Laravel中使用工厂生成一个模型的多个一对多关系时遇到了问题。工厂似乎只会为每个俱乐部生成一个ClubFixture,而不是应该为每个Club生成5个ClubFixtures。
模型
俱乐部
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Club extends Model
{
  //Table associated with the model
  protected $table = 'clubs';

   protected $fillable = ['name', 'league', 'age_group', 'colour', 'county', 'country'];

   public function fixtures(){
     return $this->hasMany('App\ClubFixture', 'club_id', 'id');
   }
}

ClubFixture

namespace App;

use Illuminate\Database\Eloquent\Model;

class ClubFixture extends Model
{
  //Table associated with the model
  protected $table = 'club_fixtures';
}

Modal Factories

$factory->define(App\Club::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'league' => $faker->word,
        'age_group' => $faker->word,
        'colour' => $faker->hexcolor,
        'county' => $faker->state,
        'country' => $faker->country,
        'emblem' => $faker->imageUrl(80, 80),
        'banner' => $faker->imageUrl,
        'matches' => $faker->randomDigit,
        'wins' => $faker->randomDigit,
        'losses' => $faker->randomDigit,
    ];
});

$factory->define(App\ClubFixture::class, function (Faker\Generator $faker) {
    return [
        'club_id' => function () {
            return factory(App\Club::class)->create()->id;
        },
        'opposition' => $faker->name,
        'address' => $faker->address,
        'datetime' => $faker->dateTimeBetween('now', '+30 weeks'),
        'type' => $faker->randomElement(['home', 'away', 'none']),
    ];
});

Database seeder

factory(App\Club::class, 100)->create()->each(function ($u) {
     factory(App\ClubFixture::class, 5)->create();
});

Expected Result: Each Club should have 5 ClubFixtures associated with it

Actual Result: Some Clubs have no ClubFixtures, some only have one.

I've tried this answer, but get an error with saveMany does not exist and relationship is null.

You can download the SQL resulting database here.

Can someone tell me what I am doing wrong here?

5个回答

8

您的模型模型工厂看起来不错,但是请使用以下种子数据来使用它们:

use Illuminate\Database\Seeder;

class ClubSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Club::class, 100)->create()->each(function($c) {
            /** @var \App\Club $c */
            $c->fixtures()->saveMany(
                factory(App\ClubFixture::class, 5)->make(['club_id' => NULL])
            );
        });
    }
}

确保您在Club模型的fixtures()关系方法上调用saveMany()方法。最后,为每个5个ClubFixtures的迭代覆盖club_id,以防止创建另一个Club。否则,您将拥有600个Clubs(而不是100个Clubs)&amp; 500个ClubFixtures。

4

你应该这样做

'club_id' => function () {
            return factory(App\Club::class,5)->create()->id;
        },

为 ClubFixture 工厂进行翻译。

4

作为 @baikho 答案的另一种选择,你可以直接指定外键而不是使用 ->saveMany() 方法。个人而言,我经常不使用 ->hasMany() 和其他关联方法,因此我使用这种方法。

use Illuminate\Database\Seeder;

class ClubSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Club::class, 100)->create()->each(function(App\Club $c) {
            factory(App\ClubFixture::class, 5)->create(['club_id' => $c->id]);
        });
    }
}

请注意,当使用这种语法时,您还需要将->make()方法更改为->create()方法。
如果您的数据库模式不在第三范式中或者您有一些条件字段,这也会很有帮助。
例如,如果用户(父表)是男性,则服装(子表)可以具有某些与女性用户不同的选项。 这些字段没有外键,但它们是基于用户条件的。
最后,您可以删除定义$c变量的PHPDoc注释,并直接将类名放入函数参数中。 这样更加简洁易懂。

2

请试试这个

模态窗口工厂

$factory->define(App\Club::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'league' => $faker->word,
        'age_group' => $faker->word,
        'colour' => $faker->hexcolor,
        'county' => $faker->state,
        'country' => $faker->country,
        'emblem' => $faker->imageUrl(80, 80),
        'banner' => $faker->imageUrl,
        'matches' => $faker->randomDigit,
        'wins' => $faker->randomDigit,
        'losses' => $faker->randomDigit,
    ];
});

$factory->define(App\ClubFixture::class, function (Faker\Generator $faker) {
    return [
        'club_id' => function () {
            return factory(App\Club::class,5)->create();
        },
        'opposition' => $faker->name,
        'address' => $faker->address,
        'datetime' => $faker->dateTimeBetween('now', '+30 weeks'),
        'type' => $faker->randomElement(['home', 'away', 'none']),
    ];
});

很不幸,当我运行 php artisan db:seed 时,它会给我返回 Property [id] does not exist on this collection instance. 的错误信息,有什么解决方案吗? - Luke Brandon Farrell

1
这是如何实现的:-

User.php (模型)

 public function UserPortfolio(){
    return $this->belongsTo(UserPortfolio::class,'id','user_id');
 }
 public function hasOnePortfolio(){
    return $this->hasOne(UserPortfolio::class,'id','user_id');
 }

数据库填充器(种子)(DatabaseSeeder (Seeds))
   $usersCount = (int)$this->command->ask('How many users do you need ? Default : ', 10);
   factory(App\Promoter::class, $usersCount)->make()->each(function ($up) {
            $up->hasOnePortfolio()->save(factory(App\UserPortfolio::class)->make());
   });
   $this->command->info('Users Created!');
   $this->command->info('Users portfolio Updated!');

UserPortfolioFactory.php(工厂)
$factory->define(UserPortfolio::class, function (Faker $faker) {
    return [
        'user_id'   => factory('App\User')->create()->id,
         ......

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接