Laravel 5.6 - как создать фабрику моделей с вертикальным столом?

Я работаю над приложением, состоящим из Leads, каждый Lead -> hasMany -> Fields. Мое приложение примет infinite количество whitelisted полей. У некоторых Leads будет много Fields, у других может быть около 5. Из-за этого я выбрал Field таблицу вертикальной, а не помещающейся во все поля, которые я принимаю по горизонтали, а затем столкнулся с ошибками MySQL. линия (таблица слишком широкая и т. д.)

Вот моя структура:

Ведущий стол

id
...

Таблица полей:

id
lead_id
field_name
field_value

Я создал фабрику моделей для моей модели Lead, которая автоматически создает 5 случайные поля, используя Faker.

У меня есть массив полей texts, numbers, dates (и т. Д.), Которые принимает мое приложение.

Field Factory:

...

$texts = config('fields.whitelist.text');
foreach ($texts as $text) {
    $fields[$text] = $faker->sentence();
}

...

$randomField = array_random(array_keys($fields));    

return [
    'field_name' => $randomField,
    'field_value' => $fields[$randomField],
];

Я делал это:

$lead = factory(Lead::class)->create()
         ->each(function ($l) {
             $l->fields()->save(factory(Field::class, 5)->make());
         });

Однако теперь у меня есть minimum массив Fields, который должен иметь каждый Lead. У меня эти minimum поля в другом конфиге.

Можно ли автоматически создать x минимум Fields на вертикальном столе, используя фабрику?

E.g.

Минимальное количество полей

first_name
date_of_birth

Как я могу написать фабрику для автоматического создания следующей структуры:

[
    'field_name' => 'first_name',
    'field_value' => '<random name>',
],
[
    'field_name' => 'date_of_birth',
    'field_value' => '<random date>',
],

Изменить: и, если возможно, не вставлять повторяющиеся field_name значения. Не то чтобы это стопроцентное нарушение условий сделки, но я хочу быть уверенным, что на 100% знаю, с какими данными я работаю, поэтому проверка x количества дубликатов, как мне кажется, была бы кошмаром.


person Kingsley    schedule 12.03.2018    source источник


Ответы (1)


Если вы хотите, чтобы в каждом Lead были эти минимальные поля, добавьте эти поля в ваше each() закрытие. Нравится:

$lead = factory(Lead::class)->create()->each(function ($lead) {
    $lead->fields()->createMany([
        'field_name' => 'first_name',
        'field_value' => $faker->firstName,
    ],
    [
        'field_name' => 'date_of_birth',
        'field_value' => $faker->dateTime(),
    ]);
    $lead->fields()->save(factory(Field::class, 3)->make());
});

Я изменил фабрику Field на 3, потому что есть 2 поля из "минимальных полей", которые вставляются для каждого Lead.

person Erik Berkun-Drevnig    schedule 12.03.2018
comment
Ах - фантастика, я не думал об этом! Однако возникла новая проблема: есть ли способ избежать дублирования одного и того же поля? - person Kingsley; 12.03.2018
comment
Что вы имеете в виду под дубликатами? Faker должен предотвратить дублирование field_values, но я думал, что намерение состояло в том, чтобы field_name дублировалось для каждого Lead. - person Erik Berkun-Drevnig; 12.03.2018
comment
Я не хочу, чтобы один и тот же field_name вводился более одного раза для одного и того же интереса. У меня есть проверка, чтобы предотвратить это в моем контроллере, но я пытаюсь выполнить модульное тестирование того же метода - person Kingsley; 12.03.2018
comment
Вы можете добавить уникальное ограничение в свою базу данных для этого - person Erik Berkun-Drevnig; 12.03.2018
comment
Да, я изначально думал об этом, но затем у нас есть некоторые другие бизнес-требования, где Lead может содержать тот же Field (тот же field_name), так что это не сработает для нас. - person Kingsley; 12.03.2018
comment
Это сработает, вам просто нужно, чтобы уникальное ограничение было для нескольких столбцов, скорее всего, это комбинация lead_id и field_name. - person Erik Berkun-Drevnig; 12.03.2018
comment
Разве он не столкнется с проблемами ограничений MySQL (иногда или постоянно, не на 100%), поскольку Laravel не будет знать об уникальном ограничении mysql, не так ли? - person Kingsley; 12.03.2018
comment
У Faker есть метод ->unique() только для этого github.com/fzaninotto/Faker - person jeremykenedy; 13.03.2018
comment
Извините, я думаю, что здесь небольшая путаница. Меня не беспокоят повторяющиеся случайные values, меня беспокоят повторяющиеся keys. Не хочу вставлять одно и то же field_name более одного раза - person Kingsley; 13.03.2018
comment
Вы можете обеспечить это на уровне базы данных с помощью $table->unique('field_name'), если хотите, чтобы он был уникальным для Lead, тогда выполните $table->unique(['field_name', 'lead_id']). Поскольку Laravel осознает эту уникальность, метод unique() в faker позаботится об этом. Проверка ограничений в другом месте вашего приложения выходит за рамки этого вопроса, но в Laravel есть средства для этого. - person Erik Berkun-Drevnig; 13.03.2018