Определение внешних ключей Laravel с фабриками моделей, от одного до одного и от одного до многих отношений без создания ненужных моделей

Недавно я пытался засеять мою базу данных с помощью посева Laravel через фабрики моделей и Faker.

Для простых схем это просто бриз, чтобы он работал :). Тем не менее, я столкнулся с несколькими проблемами при работе со сложными схемами БД, которые связаны с внешними ключами и отношениями в таблице :

  • Один к одному
  • Один ко многим
  • Многим многим

… Как описано в ссылке: внешние ключи Laravel 5.1 на фабрике моделей .

В этом разделе официальная документация предлагает запустить семена базы данных следующим образом:

public function run() { factory(App\User::class, 50)->create()->each(function ($u) { $u->posts()->save(factory(App\Post::class)->make()); }); } 

… но есть одна проблема с этим решением: при работе со многими таблицами БД и запуске многих семян (со многими отношениями между ними), обычно используется множество ненужных моделей, использующих эту методологию. Например, если мы запустили PostsTableSeeder.php перед одним из приведенных выше примеров, все эти сообщения не были бы связаны с пользователями и никогда не будут использоваться в тестах и ​​разработке …

Поэтому, пытаясь найти способ справиться с этой ситуацией, я подошел к функциональному решению, которое работает для меня и избегает ненужного создания этих «сиротских» моделей …

И я хотел поделиться им со всеми, так что это просто объясняется в ответе :).

Итак, вот мое решение:

Пример:

  • Пользователи и профили (для иллюстрации отношений « один к одному» )
  • Пользователи и сообщения (для иллюстрации отношений от одного до многих )

     // ONE TO ONE relationship (with Users already created) $factory->define(App\Profile::class, function (Faker\Generator $faker) { return [ 'user_id' => $faker->unique()->numberBetween(1, App\User::count()), // Rest of attributes... ]; }); // ONE TO MANY relationship (with Users already created) $factory->define(App\Posts::class, function (Faker\Generator $faker) { $users = App\User::pluck('id')->toArray(); return [ 'user_id' => $faker->randomElement($users), // Rest of attributes... ]; }); 

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

 $factory->define(App\Post::class, function (Faker\Generator $faker) { $user = factory('App\Models\User')->create(['email' => 'email@test.com,]); // do your relationships here (...) return [ 'user_id' => $user->id, 'title' => $faker->sentence, 'body' => $faker->paragraph, ]; } 

И я увидел еще один пример с использованием анонимной функции

 $factory->define(App\Post::class, function (Faker\Generator $faker) { return [ 'user_id' => function () { return factory(App\User::class)->create()->id; }, 'title' => $faker->sentence, 'body' => $faker->paragraph, ]; } 

Источник: https://laracasts.com/series/laravel-from-scratch-2017/episodes/22