Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

pom's avatar
Level 21

Laravel 8 Factory - One To Many (Polymorphic) Relationship

Given the following database table structure, what would go in the CommentFactory definition function?

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

All I've got is a mess!

0 likes
9 replies
lemmon's avatar

php artisan make:factory CommentFactory --model=Comment

1 like
pom's avatar
Level 21

LOL, that is the correct answer.

However, I've since reworded the question. I'm trying to work out what goes inside said CommmentFactory.

pom's avatar
Level 21
public function definition()
{
	return [
		'body' => $this->faker->sentence,
		'commentable_id' => ???,
		'commentable_type' => ???,
	]
}
lemmon's avatar

I am in the process of trying to make a One to Many Polymorphic CommentFactory.

lemmon's avatar
lemmon
Best Answer
Level 28

@pom

Here is your factory:

<?php

namespace Database\Factories;

use App\Models\Comment;
use App\Models\Post;
use App\Models\Video;
use Illuminate\Database\Eloquent\Factories\Factory;

class CommentFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = Comment::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        $commentable = $this->commentable();

        return [
            'body' => $this->faker->paragraph,
            'commentable_id' => $commentable::factory(),
            'commentable_type' => $commentable,
        ];
    }

    public function commentable()
    {
        return $this->faker->randomElement([
            Post::class,
            Video::class,
        ]);
    }
}

and when you want to control the commentable you can refer to:

https://laravel.com/docs/8.x/database-testing#polymorphic-relationships

or:

$video = Video::factory()->hasComments(3)->create();
$comments = Comment::factory()->count(3)->for(
    Video::factory(), 'commentable'
)->create();

tweak it to fit your needs, hope this helps you

13 likes
pom's avatar
Level 21

Awesome, thank you very much @lemmon 👍 that did the trick.

Esirei's avatar

I prefer using the Factory configure method for polymorphic relationships.

<?php

namespace Database\Factories;

use App\Models\Comment;
use App\Models\Post;
use App\Models\Video;
use Illuminate\Database\Eloquent\Factories\Factory;

class CommentFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'body' => $this->faker->paragraph,
        ];
    }

    public function configure()
    {
        return $this->for(
            static::factoryForModel($this->commentable()),
            'commentable',
        );
    }

    public function commentable()
    {
        return $this->faker->randomElement([
            Post::class,
            Video::class,
        ]);
    }
}
4 likes

Please or to participate in this conversation.