Skip to content

Entity Factories for JSON:API Documentation ​

This guide explains how to create and use entity factories for generating realistic documentation examples with Scribe in your JSON:API application.

Introduction ​

Entity factories are essential for generating sample data for your API documentation. The JSON:API Scribe integration uses Laravel Doctrine's factory system to create realistic entities that are transformed into JSON:API responses.

For comprehensive information about Laravel Doctrine's entity factories, refer to the official documentation.

Setting Up Entity Factories ​

1. Create Factory Files ​

Factory files should be placed in your application's database/factories directory. Each entity should have its own factory file.

Example factory file structure:

database/factories/
  ├── UserFactory.php
  ├── ArticleFactory.php
  ├── CommentFactory.php
  └── ...

2. Define Factory Structure ​

Each factory file should define how to create an instance of your entity with sample data:

php
<?php
/** @var LaravelDoctrine\ORM\Testing\Factory $factory */

use App\Entities\User;
use App\Entities\Role;
use Doctrine\Common\Collections\ArrayCollection;

$factory->define(User::class, function (Faker\Generator $faker) {
    return [
        'id' => $faker->uuid,
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => 'secret',
        // For entity relationships, use the entity() helper
        'status' => entity(UserStatus::class, 'active')->create(),
        // For collections, create ArrayCollection instances
        'roles' => new ArrayCollection([
            entity(Role::class)->create(),
        ]),
    ];
});

// You can also define named variants
$factory->defineAs(User::class, 'admin', function (Faker\Generator $faker) {
    return [
        'name' => 'Admin User',
        'email' => 'admin@example.com',
        'roles' => new ArrayCollection([
            entity(Role::class, 'admin')->create(),
        ]),
    ];
});

3. Using Factories in Seeders ​

Seeders can use factories to populate your database with test data:

php
<?php

namespace Database\Seeders;

use Doctrine\ORM\EntityManager;
use App\Entities\User;
use App\Entities\Article;

class TestDataSeeder
{
    public function run(EntityManager $em): void
    {
        // Create a user with the default factory
        $user = entity(User::class)->create();
        
        // Create a user with a named factory variant
        $admin = entity(User::class, 'admin')->create();
        
        // Create an entity with custom attributes
        $article = entity(Article::class)->create([
            'title' => 'Custom Title',
            'author' => $user,
        ]);
        
        // Create multiple entities
        entity(Article::class, 5)->create([
            'author' => $admin,
        ]);
    }
}

Best Practices for Documentation Factories ​

When creating factories for Scribe documentation, follow these best practices:

  1. Use realistic data: The Faker library helps generate realistic data for your entities.

  2. Define relationships properly: Ensure that relationships between entities are correctly defined.

  3. Create named variants: Define named variants for common entity states (e.g., 'admin', 'regular', 'premium').

  4. Use consistent IDs: For documentation, using predictable IDs can make examples easier to understand.

  5. Include all required fields: Make sure all non-nullable fields are populated.

  6. Match validation rules: The data generated should pass your application's validation rules.

Real-World Examples ​

Here are examples from the test suite:

User Factory ​

php
<?php
/** @var LaravelDoctrine\ORM\Testing\Factory $factory */

use Tests\App\Entities\User;
use Tests\App\Entities\UserStatus;
use Tests\App\Entities\Role;
use Doctrine\Common\Collections\ArrayCollection;

$factory->define(User::class, function (Faker\Generator $faker) {
    return [
        'id' => $faker->uuid,
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => 'secret',
        'status' => entity(UserStatus::class, 'active')->create(),
        'roles' => new ArrayCollection([
            Role::user(),
        ]),
    ];
});

$factory->defineAs(User::class, 'user', function (Faker\Generator $faker) {
    return [
        'id' => User::USER_ID,
        'name' => 'testing user1',
        'email' => 'test1email@test.com',
        'password' => 'secret',
        'status' => entity(UserStatus::class, 'active')->create(),
        'roles' => new ArrayCollection([
            Role::user(),
        ]),
    ];
});

Page Factory ​

php
<?php
/** @var LaravelDoctrine\ORM\Testing\Factory $factory */

use Tests\App\Entities\Page;
use Tests\App\Entities\User;

$factory->define(Page::class, function (Faker\Generator $faker) {
    return [
        'id' => $faker->uuid,
        'user' => entity(User::class)->create(),
        'title' => $faker->sentence,
        'content' => $faker->paragraphs(3, true),
    ];
});

Integration with Scribe ​

The JSON:API Scribe strategies automatically use these factories to generate documentation examples:

  1. The UseJsonApiResourceResponseStrategy creates entities using factories
  2. These entities are transformed into JSON:API responses
  3. The documentation shows realistic examples of your API's responses

No additional configuration is needed - just ensure your factories are properly defined.

Additional Resources ​