directorytree/dummy
directorytree/dummy is a Laravel/PHP package providing a lightweight dummy/test utility for generating placeholder data and fixtures. Useful for local development, demos, and automated tests where realistic sample content is needed quickly and consistently.
Installation:
composer require directorytree/dummy --dev
orchestra/testbench is recommended for Laravel integration tests.Basic Factory Creation:
use DirectoryTree\Dummy\Dummy;
use App\Models\User;
$dummy = new Dummy();
$user = $dummy->make(User::class, [
'name' => 'Test User',
'email' => 'test@example.com'
]);
First Use Case: Replace manual test data creation in unit tests:
public function test_user_creation()
{
$dummy = new Dummy();
$user = $dummy->make(User::class);
$this->assertDatabaseHas('users', [
'email' => $user->email
]);
}
Key Starting Points:
tests/ for usage examples)Dummy::make() for single instancesDummy::sequence() for batches// Basic factory
$user = Dummy::make(User::class);
// With attributes
$admin = Dummy::make(User::class, [
'role' => 'admin',
'is_active' => true
]);
// With relationships
$post = Dummy::make(Post::class, [
'user_id' => $user->id
]);
// Define states in your model
class User extends Model
{
use \DirectoryTree\Dummy\HasFactory;
protected $factoryStates = [
'admin' => ['role' => 'admin'],
'inactive' => ['is_active' => false]
];
}
// Usage
$admin = Dummy::make(User::class)->state('admin');
$inactiveAdmin = Dummy::make(User::class)
->state(['admin', 'inactive']);
// Create 10 users
$users = Dummy::sequence(User::class, 10);
// With custom attributes
$posts = Dummy::sequence(Post::class, 5, [
'title' => fn($i) => "Post $i",
'content' => 'Lorem ipsum...'
]);
// In a Laravel test
public function test_with_laravel()
{
$this->artisan('migrate'); // Setup DB
$user = Dummy::make(User::class);
$user->save();
$this->assertDatabaseHas('users', [
'email' => $user->email
]);
}
// Plain PHP class
class Product {
public $name;
public $price;
}
$products = Dummy::sequence(Product::class, 3, [
'name' => ['Laptop', 'Phone', 'Tablet'],
'price' => [999, 699, 399]
]);
PestPHP Integration:
use DirectoryTree\Dummy\Dummy;
it('creates a user', function () {
$user = Dummy::make(User::class);
expect($user)->toBeInstanceOf(User::class);
});
Factory State Testing:
public function test_factory_states()
{
$admin = Dummy::make(User::class)->state('admin');
$this->assertEquals('admin', $admin->role);
}
Database Seeding:
// In DatabaseSeeder.php
public function run()
{
Dummy::sequence(User::class, 100)->each->save();
}
Custom Attribute Expansion:
// Expand 'password' to hashed value
$user = Dummy::make(User::class, [
'password' => 'secret'
])->expand(['password' => fn($val) => bcrypt($val)]);
Non-Stringable Objects in filled():
filled(...) throws exceptions for non-stringable objects (fixed in v2.0.1).$data = Dummy::make(User::class, [
'metadata' => new \stdClass() // Will fail in <v2.0.1
]);
Late Static Binding in HasFactory:
HasFactory.^1.3.1 if experiencing closure binding issues.Laravel-Specific Helpers:
Arr helpers (introduced in v1.3.1) won't work in non-Laravel projects.array_* functions or install illuminate/support:
composer require illuminate/support
Dynamic State Conflicts:
$user = Dummy::make(User::class)
->state(['role' => 'editor', 'is_active' => true]);
Inspect Generated Data:
$data = Dummy::make(User::class)->toArray();
dd($data); // Debug output
Check Factory States:
$user = Dummy::make(User::class)->state('admin');
dd($user->getFactoryStates()); // List available states
Sequence Debugging:
$users = Dummy::sequence(User::class, 3, [
'name' => ['Alice', 'Bob', 'Charlie']
]);
dd($users->all()); // Inspect batch
Default Attribute Handling:
Arr::get() for attribute access (v1.3.1+). For older Laravel versions, override:
$dummy = new Dummy();
$dummy->setAttributeAccessor(function ($data, $key) {
return data_get($data, $key);
});
Generic Types:
$dummy = new Dummy();
$data = $dummy->make(\stdClass::class, ['prop' => 'value']);
Factory Method Parity:
has(), for()) are partially supported. For full parity, extend the Dummy class:
class CustomDummy extends Dummy {
public function has($relation, $callback)
{
// Custom implementation
}
}
Custom Attribute Providers:
$dummy = new Dummy();
$dummy->addProvider('users', function () {
return [
'name' => 'Test User',
'email' => 'test@example.com'
];
});
$user = $dummy->make(User::class, ['provider' => 'users']);
Post-Processing Hooks:
$dummy = new Dummy();
$dummy->afterMake(function ($model) {
if ($model instanceof User) {
$model->password = bcrypt($model->password);
}
});
$user = $dummy->make(User::class, ['password' => 'secret']);
Custom State Resolvers:
$dummy = new Dummy();
$dummy->resolveState('admin', function ($model) {
$model->role = 'admin';
$model->permissions = ['create', 'read'];
});
$admin = $dummy->make(User::class)->state('admin');
Batch Generation:
Dummy::sequence(User::class, 10000)->chunk(100)->each(function ($chunk) {
User::insert($chunk->toArray());
});
Memory Optimization:
$users = Dummy::sequence(User::class, 100);
// Use $users...
unset($users);
Avoid Over-Fetching:
$user = Dummy::make(User::class, [], ['email', 'name']);
How can I help you explore Laravel packages today?