Использование PHP Faker в Laravel для создания записи «уникального с» при заполнении базы данных с использованием фабрики - PullRequest
0 голосов
/ 01 июня 2018

Итак, аналогично уникальному правилу проверки (см .: https://github.com/felixkiss/uniquewith-validator),. Я хочу знать, как создать запись, в которой один столбец уникален с другим. Я хочу заполнить базу данных следующим образом.

Пример:

В таблице «шагов» 12 шагов. Каждый шаг должен иметь 5 категорий, связанных с каждой из них, которые хранятся в таблице «step_categories». Каждой из этих категорий назначаетсяуникальный номер заказа от 1 до 5, который уникален для каждого "step_id".

См. это изображение здесь для примера того, как должна выглядеть база данных: https://imgur.com/a/XYA5yyn

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

Я используюфабрика для генерации этих данных. Таким образом, фабрика имеет имя StepCategoriesFactory.php, и я явно вызываю фабрику с помощью метода create() из файла DatabaseSeeder.php.

Я думал о doiПосле этого в цикле for я дошел до того, что понял, когда позвонил 'step_id' => App\Model::all()->random()->id, чтобы получить новый идентификатор, и не смог бы убедиться, что не захватил идентификатор, для которого я только что сгенерировал 5 записей.,Я действительно новичок в Laravel, и я не уверен, с чего начать.Там нет реальной информации о SO, где фейкер может использовать уникальное с другим столбцом.Как мне поступить об этом?

ПРИМЕЧАНИЕ: Идентификатор шага не всегда будет 1-12.Идентификатор шага может отличаться в зависимости от того, был ли шаг удален и переделан.Так что просто присвоить step_id равным 1-12 не получится.

ОБНОВЛЕНИЕ: Вот код, который я только что написал, и я думаю, что я на правильном пути.Может быть.Я захватил step_id с помощью поля number, так как это всегда будет 1-12, и я выбрал IID из записи.Но сейчас я застрял на том, как сгенерировать порядок 1-5, не повторяясь.Я до сих пор не запустил его, поскольку он неполон, и я знаю, что он выдаст ошибку без правильного номера заказа.

ОБНОВЛЕНИЕ 2: Я думаю, что я на правильном путиВот.Однако я получаю неопределенную ошибку переменной.Когда я помещаю первую строку из анонимной функции, она сбрасывает порядок на «1» для каждой записи.Как сделать переменную $ autoIncrement доступной для анонимной функции?Seeder остался прежним между обновлениями.

Изображение ошибки: https://imgur.com/a/ywkd0Lb Второе изображение с ошибкой Die / Dump в терминале: https://imgur.com/a/rOGRv32

Ссылка на эту статью здесь: https://laracasts.com/discuss/channels/laravel/model-factory-increment-value-faker?page=1

ОБНОВЛЕНИЕ 3: Я забыл строку кода use ($autoIncrement) для анонимной функции.Код ниже был обновлен, но теперь я получаю другую ошибку о том, что столбец заказа имеет нулевое значение и не может быть вставлен.ясно, что это должно быть «1».Даже после того, как я позвонил своему $autoIncrement->next();, который должен увеличить его до '1', он все равно возвращает ноль в соответствии с терминалом.Однако, когда я делаю дамп на $autoIncrement->current(), он возвращает 1. Странно.

Ошибка обновления 3: https://imgur.com/a/STOmIjF

StepCategoriesFactory.php

use Faker\Generator as Faker;

$autoIncrement = autoIncrement();

$factory->define(App\StepCategory::class, function (Faker $faker) use ($autoIncrement) {
    // Generate Created At and Updated at DATETIME
    $DateTime = $faker->dateTime($max = 'now');
    $autoIncrement->next();
    $order = (int) $autoIncrement->current();

    return [
        // Generate Dummy Data
        'order' =>  $order,
        'name' => $faker->words(4, true),
        'created_at' => $DateTime,
        'updated_at' => $DateTime,
    ];
});

function autoIncrement()
{
    for ($i = 0; $i < 5; $i++) {
        yield $i;
    }
}

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

Ответы [ 3 ]

0 голосов
/ 04 июня 2018

Извините, если вы не поняли мою точку зрения, поэтому я попытаюсь объяснить это в коде

    use Illuminate\Database\Seeder;


$factory->define(App\StepCategory::class, function (Faker $faker) {
    // Generate Created At and Updated at DATETIME
    $DateTime = $faker->dateTime($max = 'now');
    $step_id = function () {
            return factory('App\Step')->create()->id;
        };

    return [
        // Generate Dummy Data
       'step_id' => $step_id,
        'order' => uniqueOrder($step_id),
        'name' => $faker->words(4, true),
        'created_at' => $DateTime,
        'updated_at' => $DateTime,
    ];
});

function uniqueOrder($step_id)
{
    $unique = rand(1,5);
    do {
       $unique = rand(1,5);
     }
     while(StepCategory::where('step_id', $step_id)->andWhere( 'order', $unique)->exists())

  return $unique;

}
0 голосов
/ 04 июня 2018

НАКОНЕЦ РЕШЕНО!

Так что я взял ответы каждого и долго думал над использованием цикла for для создания номера заказа.1-5.Проблема, с которой я столкнулся в конце, состояла в том, что переменная $ i не сбрасывалась.Поэтому после выхода я должен был проверить, равна ли переменная $ i 5, а затем сбросить ее до нуля.

Вот код!

StepCategories.php

use Faker\Generator as Faker;

$autoIncrement = autoIncrement();

$factory->define(App\StepCategory::class, function (Faker $faker) use ($autoIncrement) {
    // Generate Created At and Updated at DATETIME
    $DateTime = $faker->dateTime($max = 'now');

    // Get the next iteration of the autoIncrement Function
    $autoIncrement->next();
    // Assign the current $i value to a typecast variable.
    $order = (int) $autoIncrement->current();


    return [
        // Generate Dummy Data
        'order' =>  $order,
        'name' => $faker->words(4, true),
        'created_at' => $DateTime,
        'updated_at' => $DateTime,
    ];
});

function autoIncrement()
{
    // Start a loop
    for ($i = 0; $i <= 5; $i++) {
        // Yield the current value of $i
        yield $i;
        // If $i is equal to 5, that must mean the start of a new loop
        if($i == 5) {
            // Reset $i to 0 to start over.
            $i = 0;
        }
    }
}

DatabaseSeeder.php

// Generate Dummy Categories
// Run the factory 12 times
foreach(range(1, 12) as $i) {
    // Generate 5 entries each time
    factory(App\StepCategory::class, 5)->create([
        // Since all steps have a number 1-12 grab the step by the number column and get it's ID
        'step_id' => App\Step::where('number', '=', $i)->first()->id,
    ]);
}

Спасибо всем, кто помог!

0 голосов
/ 04 июня 2018

, например, если имя вашей модели Step является Steps:

$allSteps = Steps::all();
foreach($allSteps as $step){
   for($i=1;$i<6;$i++){
     //insert to table $step->id , $i  for example 
     DB::table('yourTableName')->insert([
           'name'=>'Step '.$step->id.'- Category '.$i , 
           'order'=>$i , 
          'step_id'=>$step->id
     ]);
    }
}
...