How can I create a database seeder factory for the following configuration?
User
// create_users_table.php
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
...
}
// User.php
public function notes()
{
return $this->morphMany('App\Note', 'noteable');
}
Complex
// create_complex_table.php
Schema::create('complex', function (Blueprint $table) {
$table->increments('id');
...
}
// Complex.php
public function notes()
{
return $this->morphMany('App\Note', 'noteable');
}
Notes
// create_notes_table.php
Schema::create('notes', function (Blueprint $table) {
$table->increments('id');
$table->integer('noteable_id');
$table->string('noteable_type');
...
}
// Note.php
public function noteable()
{
return $this->morphTo();
}
I am struggling to see the most robust way of ensuring that I am not just filling in random id
's that may not exist.
Database seeder is used to populate tables with data. Model factories is a convenient centralized place to define how your models should be populated with fake data.
Laravel has a feature called model factories that allows you to build fake data for your models. It is very useful for testing and seeding fake data into your database to see your code in action before any real user data comes in.
According to Laravel's official documentation, “factories are classes that extend Laravel's base factory class and define a model property and definition method.” Just think about it this way.
A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.
I have improved upon HyperionX's answer and removed the static elements from it.
$factory->define(App\Note::class, function (Faker $faker) {
$noteable = [
App\User::class,
App\Complex::class,
]; // Add new noteables here as we make them
$noteableType = $faker->randomElement($noteables);
$noteable = factory($noteableType)->create();
return [
'noteable_type' => $noteableType,
'noteable_id' => $noteable->id,
...
];
});
Basically, we pick one of the noteable classes at random, then call it's own factory to get an instance of noteable, thus we get rid of the staticness of the OP's answer.
If you are using a morph map the given solutions won't work because the type won't be the same as the class name.
This will work in combination with a morph map.
Until Laravel 7
$factory->define(App\Note::class, function (Faker $faker) {
$noteable = $faker->randomElement([
App\User::class,
App\Complex::class,
]);
return [
'noteable_id' => factory($noteable),
'noteable_type' => array_search($noteable, Relation::$morphMap),
...
];
});
From Laravel 8
public function definition(): array
{
/** @var HasFactory $noteable */
$noteable = $this->faker->randomElement([
App\User::class,
App\Complex::class,
]);
return [
'noteable_type' => array_search($noteable, Relation::$morphMap),
'noteable_id' => $noteable::factory(),
];
}
More information about morph map could be found here: https://laravel.com/docs/8.x/eloquent-relationships#custom-polymorphic-types
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With