首页 > 解决方案 > 带有递归表的 Laravel 播种器循环在每次增量后都无法看到插入的数据

问题描述

我正在创建一个 Laravel 工厂来创建产品模型,然后使用播种器文件创建 100 个产品工厂。产品模型有一个自引用列,我知道如果数据库中没有产品模型,则该列应该为空。但在那之后,我想获取一个随机的产品 ID 并将其扔到列中。我正在检查产品型号计数,如果它大于 0,我可以抓取随机产品,否则只需将该列设置为空。但是在播种循环中,每个查询都返回 0 列,我不知道为什么。

这就是我试图在工厂里做的事情。

<?php

use Faker\Generator as Faker;
use Illuminate\Support\Facades\Log;

$factory->define(App\Product::class, function (Faker $faker) {
    // Logging count to see if it's changing.
    Log::debug(App\Product::count());

    // For the first insert I know there are no products
    // so I want to set the first row to null.
    $product = null;
    // While on the second row the count should be 1
    // but it's returning 0 every time in the seeder loop
    if (App\Product::count() < 0) {
        $product = App\Product::all()->random()->id;
    }

    return [
        'model' => $faker->word,
        'monitor_setup_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'monitor_monthly_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'manage_setup_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'manage_monthly_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'maximize_setup_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'maximize_monthly_price' => $faker->optional()->randomFloat(2, 0, 1000),
        'decommissioned' => 0,
        'category_id' => factory(App\Category::class)->create(),
        'vendor_id' => factory(App\Vendor::class)->create(),
        'type_id' => factory(App\Type::class)->create(),
        'product_id' => $product,
        'created_by' => App\User::all()->random()->id,
        'updated_by' => App\User::all()->random()->id,
        'created_at' => $faker->dateTimeBetween('-2 years', '-1 month'),
        'updated_at' => $faker->dateTimeThisMonth()
    ];
});

播种机只是运行工厂 100 次。

<?php

use Illuminate\Database\Seeder;

class ProductsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(App\Product::class, 100)->create();
    }
}

我的解决方案是在播种机中手动运行 for 循环。这对我来说并不那么干净,我也想确切地知道为什么代码会这样工作。

旁注:我的问题类似于[在 Laravel 中使用工厂播种递归表],但此处的解决方案不起作用。

带有递归表的 Seeder 循环无法在每次增量后看到插入的数据。为什么每次循环后计数都返回 0?

标签: phplaravellaravel-seeding

解决方案


我猜这是因为工厂首先多次为给定模型创建构建器,然后创建模型集合并将它们保存到数据库中,所以即使您在每次迭代中获取所有产品,它们中的任何一个都有已经持久化到数据库了。

也许你可以这样做

$factory->define(App\Product::class, function (Faker $faker) use (&$id) {
    return [
        // ...
        'product_id' => rand(1, $id++),
        // ...
    ];
});

你可能还想看看

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/helpers.php#L493

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Eloquent/Factory.php#L255

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Database/Eloquent/FactoryBuilder.php

看到整个事情的细节。


推荐阅读