【问题标题】:Laravel 8: Passing Factory properties into children relationshipsLaravel 8:将工厂属性传递给子关系
【发布时间】:2021-06-30 19:29:54
【问题描述】:

我们目前正在开发一个 laravel 8 应用程序。我们正在尝试创建工厂来为手动/基于开发人员的应用程序测试创建一些虚拟数据。

我的主 Database-Seeder 的当前代码如下:

class DatabaseSeeder extends Seeder
{

    public function run()
    {
        $this->call([
            UserTableSeeder::class,
        ]);
        \App\Models\User::factory(10)->create();
        \App\Models\Activity::factory(5)->create();

/* 1. try
        $tenFact = \App\Models\Tenant::factory(2)->has(
            \App\Models\Project::factory(2)->state(
                function (array $attributes, \App\Models\Tenant $tenant) {
                    return ['tenant_id' => $attributes['id']];
                } 
            )->hasTasks(5)->hasLocation()
        )->hasContracts(3)->create();

        */
        
/* Currently being used: */
        \App\Models\Tenant::factory(10)->has(
            \App\Models\Project::factory(5)->hasTasks(5)->hasLocation()
            )->hasContracts(3)->create();

    }

ProjectFactory.php:

class ProjectFactory extends Factory
{

    protected $model = Project::class;

    public function definition()
    {
        return [
            'name' => 'Projekt: '. $this->faker->name,
            'budget' => $this->faker->randomDigitNotNull*1000, 
            'progress' => $this->faker->randomDigitNotNull*10, 
            'budget_used' => $this->faker->randomDigitNotNull*50, 
            //'tenant_id' => Tenant::factory(),
            'location_id' => Location::factory()->hasTenant(1),
        ];
    }
}

LocationFactory.php:

class LocationFactory extends Factory
{

    protected $model = Location::class;

    public function definition()
    {
        return [
            'name' => 'Standort: ' . $this->faker->company,
            'street' => $this->faker->streetName,
            'house_number' => $this->faker->buildingNumber,
            'house_addition' => $this->faker->secondaryAddress,
            'zip' => $this->faker->postcode,
            'city' => $this->faker->city,
            'tenant_id' => Tenant::factory(),
        ];
    }
}

我们的关系如下所示:

Tenant 
  |-- Project (has: tenant_id, but also has location_id)
  |   | -- Task (has: project_id)
  |-- Locations (has: tenant_id)
  |-- Contracts (has: tenant_id)

使用上述命名的租户工厂创建数据集时,会发生以下情况:

  • Tenant->id 正在传递给 Project(tenant_id) 但是:Tenant->id 没有被传递到 Location(这取决于租户 id,但也用于 Project)。

我们如何将 \App\Models\Tenant::factory(10) 的 id 传递给 Project::factory(5)->hasTasks(5)->hasLocation()?

此外,我们确实有一个问题,即使我们请求 10 个租户,我们也会得到大约 60 个,因为位置/项目在应该使用现有对象时会创建新对象。

【问题讨论】:

    标签: laravel nested relationship factory


    【解决方案1】:
    class ProjectFactory extends Factory
    {
     $location_ids = App\Models\Location::pluck('id')->toArray();
    
        protected $model = Project::class;
    
        public function definition()
        {
            return [
                'name' => 'Projekt: '. $this->faker->name,
                'budget' => $this->faker->randomDigitNotNull*1000, 
                'progress' => $this->faker->randomDigitNotNull*10, 
                'budget_used' => $this->faker->randomDigitNotNull*50, 
                //'tenant_id' => Tenant::factory(),
                'location_id'=> $faker->randomElement($location_ids),
            ];
        }
    }
    
    class LocationFactory extends Factory
    {
        $tenant_ids = App\Models\Tenant::pluck('id')->toArray();
        protected $model = Location::class;
    
        public function definition()
        {
            return [
                'name' => 'Standort: ' . $this->faker->company,
                'street' => $this->faker->streetName,
                'house_number' => $this->faker->buildingNumber,
                'house_addition' => $this->faker->secondaryAddress,
                'zip' => $this->faker->postcode,
                'city' => $this->faker->city,
                'tenant_id'=> $faker->randomElement($tenant_ids),
            ];
        }
    }
    

    【讨论】:

    • 我无法完成这项工作,因为它导致项目属于tenant_id = 1,而包含位置属于tenant_id = 2。我发布了一个可行的解决方案。
    【解决方案2】:

    我放弃了使用 Tenant-Factory 的链式用法 - 我最终使用了一些 for-Loop,通过 laravel for() 和 state() 方法将相关对象连接到每个用户:

           for ($i=0; $i < 10 ; $i++) { 
                $tenant = \App\Models\Tenant::factory()->hasContracts(3)->create();
                for ($j=0; $j < 5; $j++) { 
                    $location = \App\Models\Location::factory(1)->for($tenant)->create();
                    $project = \App\Models\Project::factory(1)->state([
                        'location_id' => $location->first()['id'],
                        'tenant_id' => $tenant['id']])->hasTasks(5)->create();
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2020-06-18
      • 2019-04-01
      • 1970-01-01
      • 2023-03-06
      • 2020-12-28
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      相关资源
      最近更新 更多