Цикл сеялки Laravel с рекурсивной таблицей не может видеть вставленные данные после каждого приращения - PullRequest
0 голосов
/ 15 января 2019

Я создаю фабрику Laravel для создания моделей продуктов, а затем использую файл сеялки для создания 100 фабрик продуктов. Модель продукта имеет столбец с самообращением, и я знаю, что если в базе данных нет моделей продуктов, этот столбец должен быть нулевым. Но после этого я хочу получить случайный идентификатор продукта и добавить его в столбец. Я проверяю количество моделей продуктов, и если оно больше 0, я могу получить случайный продукт, иначе просто установите для столбца значение NULL. Но в то время как в цикле seeder каждый запрос возвращает 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 ], за исключением того, что решение здесь не работает.

  • Ларавел 5.7
  • PHP 7.3.1

Цикл Seeder с рекурсивной таблицей не может видеть вставленные данные после каждого приращения. Почему счетчик возвращает 0 после каждого цикла?

1 Ответ

0 голосов
/ 15 января 2019

Я предполагаю, что это потому, что фабрика сначала создает конструктор для данной модели несколько раз, а затем создает коллекцию моделей и сохраняет их в базе данных, поэтому даже если вы получаете все продукты на каждой итерации, любой из них еще сохранены в базе данных.

Может быть, вы могли бы сделать как

$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

чтобы увидеть детали всего этого.

...