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
/** @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
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:
Use realistic data: The Faker library helps generate realistic data for your entities.
Define relationships properly: Ensure that relationships between entities are correctly defined.
Create named variants: Define named variants for common entity states (e.g., 'admin', 'regular', 'premium').
Use consistent IDs: For documentation, using predictable IDs can make examples easier to understand.
Include all required fields: Make sure all non-nullable fields are populated.
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
/** @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
/** @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:
- The
UseJsonApiResourceResponseStrategy
creates entities using factories - These entities are transformed into JSON:API responses
- The documentation shows realistic examples of your API's responses
No additional configuration is needed - just ensure your factories are properly defined.