This guide showcases real-world examples inspired by the Laravel Cloud API, demonstrating how to combine all of Data Factory's features to create complex, realistic test data.
A simple class representing an organization:
<?php
use FBarrento\DataFactory\Factory;
use FBarrento\DataFactory\Concerns\HasDataFactory;
class Organization
{
use HasDataFactory;
public function __construct(
public string $id,
public string $name,
) {}
protected static function newFactory(): OrganizationFactory
{
return new OrganizationFactory();
}
}The factory generates organizations with realistic company names:
<?php
class OrganizationFactory extends Factory
{
protected function definition(): array
{
return [
'id' => $this->fake->uuid(),
'name' => $this->fake->company(),
];
}
}The Repository class represents a Git repository:
<?php
class Repository
{
use HasDataFactory;
public function __construct(
public string $id,
public string $name,
public string $fullName,
public string $defaultBranch,
) {}
protected static function newFactory(): RepositoryFactory
{
return new RepositoryFactory();
}
}The factory creates realistic repository data with a username/repo format:
<?php
class RepositoryFactory extends Factory
{
protected function definition(): array
{
$username = $this->fake->userName();
$repoName = $this->fake->slug();
return [
'id' => $this->fake->uuid(),
'name' => $repoName,
'fullName' => "{$username}/{$repoName}",
'defaultBranch' => 'main',
];
}
public function legacy(): static
{
return $this->state([
'defaultBranch' => 'master',
]);
}
}The Deployment class represents a deployment with various states and timestamps. It uses an enum for type-safe status values:
<?php
enum DeploymentStatus: string
{
case Pending = 'pending';
case Running = 'deployment.running';
case Succeeded = 'deployment.succeeded';
case Failed = 'deployment.failed';
}
class Deployment
{
use HasDataFactory;
public function __construct(
public string $id,
public DeploymentStatus $status,
public string $branchName,
public string $commitHash,
public string $commitMessage,
public ?string $failureReason = null,
public string $phpMajorVersion = '8.4',
public bool $usesOctane = false,
public ?\DateTimeInterface $startedAt = null,
public ?\DateTimeInterface $finishedAt = null,
) {}
protected static function newFactory(): DeploymentFactory
{
return new DeploymentFactory();
}
}The DeploymentFactory provides different deployment states with realistic timestamps and failure reasons:
<?php
class DeploymentFactory extends Factory
{
protected function definition(): array
{
return [
'id' => $this->fake->uuid(),
'status' => $this->fake->randomElement(DeploymentStatus::cases()),
'branchName' => 'main',
'commitHash' => $this->fake->sha1(),
'commitMessage' => $this->fake->sentence(),
'failureReason' => null,
'phpMajorVersion' => '8.4',
'usesOctane' => false,
'startedAt' => null,
'finishedAt' => null,
];
}
public function pending(): static
{
return $this->state([
'status' => DeploymentStatus::Pending,
]);
}
public function running(): static
{
return $this->state([
'status' => DeploymentStatus::Running,
'startedAt' => $this->fake->dateTimeBetween('-10 minutes', 'now'),
]);
}
public function succeeded(): static
{
$startedAt = $this->fake->dateTimeBetween('-1 hour', '-30 minutes');
return $this->state([
'status' => DeploymentStatus::Succeeded,
'startedAt' => $startedAt,
'finishedAt' => $this->fake->dateTimeBetween($startedAt, 'now'),
]);
}
public function failed(): static
{
$startedAt = $this->fake->dateTimeBetween('-1 hour', '-30 minutes');
return $this->state([
'status' => DeploymentStatus::Failed,
'failureReason' => $this->fake->randomElement([
'Build failed: npm install exited with code 1',
'Deployment timeout: exceeded 15 minute limit',
'Health check failed: application not responding',
'Database migration failed',
]),
'startedAt' => $startedAt,
'finishedAt' => $this->fake->dateTimeBetween($startedAt, 'now'),
]);
}
public function withOctane(): static
{
return $this->state([
'usesOctane' => true,
]);
}
}The Environment class represents a deployment environment with configuration and optional current deployment:
<?php
class Environment
{
use HasDataFactory;
public function __construct(
public string $id,
public string $name,
public string $slug,
public string $status,
public string $vanityDomain,
public string $phpMajorVersion,
public int $nodeVersion,
public bool $usesOctane,
public bool $usesHibernation,
public ?Deployment $currentDeployment = null,
public \DateTimeInterface $createdAt,
) {}
protected static function newFactory(): EnvironmentFactory
{
return new EnvironmentFactory();
}
}The factory provides states for production, staging, and preview environments with nested deployments:
<?php
class EnvironmentFactory extends Factory
{
protected function definition(): array
{
return [
'id' => $this->fake->uuid(),
'name' => $this->fake->word(),
'slug' => $this->fake->slug(),
'status' => 'stopped',
'vanityDomain' => $this->fake->domainName(),
'phpMajorVersion' => '8.3',
'nodeVersion' => 20,
'usesOctane' => false,
'usesHibernation' => false,
'currentDeployment' => null,
'createdAt' => $this->fake->dateTimeBetween('-6 months'),
];
}
public function production(): static
{
return $this->state([
'name' => 'production',
'slug' => 'production',
'status' => 'running',
'phpMajorVersion' => '8.4',
'nodeVersion' => 22,
'usesOctane' => true,
'currentDeployment' => fn () => Deployment::factory()->succeeded()->make(),
]);
}
public function staging(): static
{
return $this->state([
'name' => 'staging',
'slug' => 'staging',
'status' => 'running',
'phpMajorVersion' => '8.4',
'currentDeployment' => fn () => Deployment::factory()->succeeded()->make(),
]);
}
public function preview(): static
{
return $this->state([
'name' => $this->fake->word() . '-preview',
'slug' => $this->fake->slug() . '-preview',
'status' => 'hibernating',
'usesHibernation' => true,
]);
}
public function withDeployment(string $status = 'succeeded'): static
{
return $this->state([
'status' => 'running',
'currentDeployment' => fn () => Deployment::factory()->$status()->make(),
]);
}
}The Application class brings everything together with nested resources:
<?php
class Application
{
use HasDataFactory;
public function __construct(
public string $id,
public string $name,
public string $slug,
public string $region,
public Repository $repository,
public Organization $organization,
public ?Environment $defaultEnvironment = null,
public array $environments = [],
public array $deployments = [],
public \DateTimeInterface $createdAt,
) {}
protected static function newFactory(): ApplicationFactory
{
return new ApplicationFactory();
}
}The factory demonstrates advanced patterns with multiple nested factories, helper methods, and sequences:
<?php
class ApplicationFactory extends Factory
{
protected function definition(): array
{
return [
'id' => $this->fake->uuid(),
'name' => $this->fake->company() . ' App',
'slug' => $this->fake->slug(),
'region' => $this->fake->randomElement(['us-east-1', 'us-east-2', 'us-west-2', 'eu-west-1']),
'repository' => Repository::factory(),
'organization' => Organization::factory(),
'defaultEnvironment' => null,
'environments' => [],
'deployments' => [],
'createdAt' => $this->fake->dateTimeBetween('-1 year', '-1 month'),
];
}
public function withEnvironments(): static
{
return $this->state([
'defaultEnvironment' => fn () => Environment::factory()->production()->make(),
'environments' => fn () => [
Environment::factory()->production()->make(),
Environment::factory()->staging()->make(),
Environment::factory()->preview()->make(),
],
]);
}
public function withDeployments(int $count = 5): static
{
return $this->state([
'deployments' => fn () => Deployment::factory()
->count($count)
->sequence(
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Failed]
)
->make(),
]);
}
public function complete(): static
{
return $this
->withEnvironments()
->withDeployments(10);
}
}$application = Application::factory()->make();$application = Application::factory()->withEnvironments()->make();
echo $application->defaultEnvironment->name; // "production"
echo count($application->environments); // 3$application = Application::factory()->complete()->make();
// Has repository, organization, 3 environments, and 10 deployments
echo $application->repository->fullName;
echo $application->organization->name;
echo count($application->environments); // 3
echo count($application->deployments); // 10$applications = Application::factory()
->complete()
->count(5)
->make();$application = Application::factory()
->withEnvironments()
->make([
'name' => 'My Custom Application',
'region' => 'eu-west-1',
'repository' => Repository::factory()->legacy()->make(),
]);use FBarrento\DataFactory\ArrayFactory;
class DeploymentResourceFactory extends ArrayFactory
{
protected function definition(): array
{
return [
'id' => $this->fake->uuid(),
'type' => 'deployments',
'attributes' => [
'status' => DeploymentStatus::Succeeded->value,
'branch_name' => 'main',
'commit_hash' => $this->fake->sha1(),
'commit_message' => $this->fake->sentence(),
'started_at' => $this->fake->iso8601(),
'finished_at' => $this->fake->iso8601(),
],
'relationships' => [
'environment' => [
'data' => [
'type' => 'environments',
'id' => $this->fake->uuid(),
],
],
],
];
}
}
$response = [
'data' => DeploymentResourceFactory::new()->make(),
];class ApplicationCollectionFactory extends ArrayFactory
{
protected function definition(): array
{
return [
'data' => fn () => ApplicationResourceFactory::new()->count(15)->make(),
'links' => [
'first' => 'https://cloud.laravel.com/api/applications?page=1',
'last' => 'https://cloud.laravel.com/api/applications?page=5',
'prev' => null,
'next' => 'https://cloud.laravel.com/api/applications?page=2',
],
'meta' => [
'current_page' => 1,
'from' => 1,
'last_page' => 5,
'per_page' => 15,
'to' => 15,
'total' => 73,
],
];
}
public function page(int $page, int $totalPages = 5): static
{
return $this->state([
'links' => [
'first' => 'https://cloud.laravel.com/api/applications?page=1',
'last' => "https://cloud.laravel.com/api/applications?page={$totalPages}",
'prev' => $page > 1 ? "https://cloud.laravel.com/api/applications?page=" . ($page - 1) : null,
'next' => $page < $totalPages ? "https://cloud.laravel.com/api/applications?page=" . ($page + 1) : null,
],
'meta' => [
'current_page' => $page,
],
]);
}
}
// First page
$page1 = ApplicationCollectionFactory::new()->make();
// Second page
$page2 = ApplicationCollectionFactory::new()->page(2)->make();
// Convert to JSON
$json = json_encode($page1, JSON_PRETTY_PRINT);class ApplicationResourceFactory extends ArrayFactory
{
protected function definition(): array
{
$appId = $this->fake->uuid();
$repoId = $this->fake->uuid();
$orgId = $this->fake->uuid();
return [
'data' => [
'id' => $appId,
'type' => 'applications',
'attributes' => [
'name' => $this->fake->company() . ' App',
'slug' => $this->fake->slug(),
'region' => 'us-east-2',
'created_at' => $this->fake->iso8601(),
],
'relationships' => [
'repository' => [
'data' => ['type' => 'repositories', 'id' => $repoId],
],
'organization' => [
'data' => ['type' => 'organizations', 'id' => $orgId],
],
'environments' => [
'data' => fn () => [
['type' => 'environments', 'id' => $this->fake->uuid()],
['type' => 'environments', 'id' => $this->fake->uuid()],
],
],
],
],
'included' => [
[
'id' => $repoId,
'type' => 'repositories',
'attributes' => [
'name' => $this->fake->slug(),
'full_name' => $this->fake->userName() . '/' . $this->fake->slug(),
],
],
[
'id' => $orgId,
'type' => 'organizations',
'attributes' => [
'name' => $this->fake->company(),
],
],
],
];
}
}
$response = ApplicationResourceFactory::new()->make();// Simulate a week of deployments
$deployments = Deployment::factory()
->count(20)
->sequence(fn (Sequence $seq) => [
'branchName' => $seq->index % 5 === 0 ? 'main' : "feature/task-{$seq->index}",
'commitMessage' => "Deploy #{$seq->index}: {$this->fake->sentence()}",
])
->sequence(
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Succeeded],
['status' => DeploymentStatus::Failed]
)
->make();$environments = Environment::factory()
->count(4)
->sequence(
['name' => 'production', 'status' => 'running', 'usesOctane' => true],
['name' => 'staging', 'status' => 'running', 'usesOctane' => true],
['name' => 'development', 'status' => 'running', 'usesOctane' => false],
['name' => 'preview', 'status' => 'hibernating', 'usesHibernation' => true]
)
->make();- Testing - Use these examples in PEST tests
- Nested Factories - Deep dive into nested patterns
- Array Factories - More on JSON:API responses