【问题标题】:Laravel : using model factories to generate one-to-many relationshipsLaravel:使用模型工厂生成一对多关系
【发布时间】:2018-08-11 02:59:28
【问题描述】:

我在使用 Laravel 中的工厂为模型生成多个一对多关系时遇到问题。工厂似乎每个俱乐部只生成一个 ClubFixture,而他们应该为每个俱乐部生成 5 个 ClubFixture。

模型

俱乐部

<?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');
   }
}

俱乐部夹具

namespace App;

use Illuminate\Database\Eloquent\Model;

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

模态工厂

$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']),
    ];
});

数据库播种器

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

预期结果:每个俱乐部应该有 5 个与之关联的 ClubFixtures

实际结果:有些俱乐部没有球具,有些只有一个。

我已经尝试过这个answer,但得到一个错误,即 saveMany 不存在并且关系为空。

您可以下载 SQL 结果数据库here

谁能告诉我我在这里做错了什么?

【问题讨论】:

    标签: laravel eloquent one-to-many factory


    【解决方案1】:

    试试这个

    模态工厂

    $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.,有什么解决方案吗?
    【解决方案2】:

    您的 ModelsModel Factory 看起来不错,但可以将它们与此播种机一起使用:

    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 个 ClubFixture 的每次迭代覆盖 club_id,以防止再次创建俱乐部。否则,您最终会得到 600 个球杆(而不是 100 个球杆)和 500 个球杆夹具。

    【讨论】:

      【解决方案3】:

      你应该这样做

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

      用于 ClubFixture 工厂。

      【讨论】:

        【解决方案4】:

        这是我如何做到这一点的:-

        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(种子)

           $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,
                 ......
        

        【讨论】:

          【解决方案5】:

          作为@baikho 答案的替代方案,您可以直接指定外键,而不是使用-&gt;saveMany() 方法。我个人使用这个,因为我通常不使用-&gt;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]);
                  });
              }
          }
          

          请注意,在使用此语法时,您还希望将 -&gt;make() 方法更改为 -&gt;create() 方法。

          如果您的数据库架构不是第三规范化形式或您有一些条件字段,这也很有帮助。

          例如,如果用户(父表)是男性,则 Clothing(子表)可以具有与用户是女性不同的某些选项。这些字段没有外键,但它们以用户为条件。

          最后,您可以删除定义 $c 变量的 PHPDoc 注释,并将类名直接弹出到函数参数中。这样会更干净、更易读。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-03-21
            • 2018-06-13
            • 2021-03-02
            • 2015-12-09
            • 2017-04-11
            • 2017-11-24
            • 2018-01-10
            • 2015-10-21
            相关资源
            最近更新 更多