Generators
This document provides a detailed comparison between the available fake data generators and a migration guide for switching between them.
Available Generators
Faker
- Package: FakerPHP/Faker
- Minimum PHP: 8.2+ (project requirement)
- Install:
composer require --dev fakerphp/faker - Best for: Mature, feature-rich data generation with extensive locale support
Dummy
- Package: johnykvsky/dummygenerator
- Minimum PHP: 8.3+
- Install:
composer require --dev johnykvsky/dummygenerator - Best for: Modern PHP 8.3+ projects, native enum support, the alternative generator adapter
How the default is chosen
When FixtureFactories.generatorType is unset and you don't pass $type to CakeGeneratorFactory::create(), the plugin auto-detects which library is installed:
- Explicit
Configure::write('FixtureFactories.generatorType', ...)always wins. - Otherwise, if
fakerphp/fakeris installed,'faker'is used. - Otherwise, if
johnykvsky/dummygeneratoris installed,'dummy'is used. - If neither is installed, a
FixtureFactoryExceptionis thrown pointing at the install commands.
This means single-library installs "just work" with no extra config, while existing setups that have both libraries installed keep their previous faker-first behavior.
Key Differences
1. Enum Support
Faker (requires shim methods):
// Get random enum case (returns the enum object)
$status = $this->getGenerator()->enumCase(TestStatus::class);
// Get random backed enum value (returns string/int)
$statusValue = $this->getGenerator()->enumValue(TestStatus::class);DummyGenerator (native support):
// Get random enum case (native method)
$status = $this->getGenerator()->enumCase(TestStatus::class);
// Get random backed enum value
$statusValue = $this->getGenerator()->enumValue(TestStatus::class);2. Locale Support
Faker:
- Full locale support with locale-specific data
- 50+ locales available
- Example:
CakeGeneratorFactory::create('fr_FR')
DummyGenerator:
- The plugin adapter ignores the locale parameter
- Use Faker when locale-specific output matters
- Focuses on generic data generation
3. Method Compatibility
Most methods work identically across both generators. However, some methods are shimmed for compatibility:
| Method | Faker | DummyGenerator | Notes |
|---|---|---|---|
uuid() | Native | Mapped to uuid4() | Both generate valid UUIDs |
realText() | Native | Mapped to text() | Same behavior |
randomAscii() | Native | Shimmed | Returns ASCII character (33-126) |
enumCase() | Shimmed | Native | Recommended for enums |
enumValue() | Shimmed | Shimmed | Works on both |
4. Seeding Behavior
Both generators support seeding for reproducible test data. By default, factories are seeded with 1234. Each factory class mixes its class name into that seed, so two factories with the same definition still produce different values. A shared generator set via BaseFactory::setDefaultGenerator() uses the plain seed and one sequence for all factories. Faker seeds PHP's process-wide mt_rand state, so with Faker a factory's values can still shift when another factory creates its generator first; DummyGenerator keeps its random state per generator. You can configure a different seed globally:
Configure::write('FixtureFactories.seed', 9999);Faker:
$generator->seed(1234);DummyGenerator:
$generator->seed(1234); // Uses XoshiroRandomizer internally5. Measuring performance
Generator overhead depends on the selected methods, associations and database writes. Measure representative factories in your own test suite before choosing a generator for speed. This plugin does not provide comparative timing or memory benchmarks.
Switching Generators
Configuration
Set the generator type in your tests/bootstrap.php or test configuration:
use Cake\Core\Configure;
// Use Faker
Configure::write('FixtureFactories.generatorType', 'faker');
// Use DummyGenerator
Configure::write('FixtureFactories.generatorType', 'dummy');If you have only one of the two libraries installed, you can leave this key unset — the plugin auto-detects which one is available.
Or set it per-factory:
$article = ArticleFactory::new()
->setGenerator('dummy')
->build();Note: By default,
setGenerator()only affects the current factory instance. SetFixtureFactories.instanceLevelGeneratortofalseif you need the legacy global behavior. See Fixture Factories.
Migration Guide: Faker → DummyGenerator
Step 1: Install DummyGenerator
composer require --dev johnykvsky/dummygeneratorStep 2: Update Configuration
// In tests/bootstrap.php
Configure::write('FixtureFactories.generatorType', 'dummy');Step 3: Test Your Factories
Run your test suite to ensure compatibility:
vendor/bin/phpunitStep 4: (Optional) Remove Faker
If you no longer need Faker:
composer remove --dev fakerphp/fakerMigration Guide: DummyGenerator → Faker
Step 1: Install Faker
composer require --dev fakerphp/fakerStep 2: Update Configuration
// In tests/bootstrap.php
Configure::write('FixtureFactories.generatorType', 'faker');Step 3: Update Enum Methods (if using)
enumCase() and enumValue() work on both, so no changes needed unless you're using DummyGenerator-specific features.
Step 4: Adjust for Locale (if needed)
Take advantage of Faker's locale support:
$generator = CakeGeneratorFactory::create('fr_FR');Step 5: Test Your Factories
Run your test suite:
vendor/bin/phpunitCommon Pitfalls
1. PHP Version Requirements
Problem: DummyGenerator requires PHP 8.3+
Solution: Check your PHP version before switching:
php -v2. Locale-Specific Data
Problem: DummyGenerator doesn't support locale-specific data like Faker
Solution: If you need locale-specific data, stick with Faker or implement custom data providers
3. Unique Values
Problem: Different retry mechanisms for unique values
Solution: Both support unique() modifier, but DummyGenerator has a custom retry mechanism (10,000 attempts vs Faker's default)
// Works on both
$generator->unique()->email();Best Practices
1. Keep Factory Code Generator-Agnostic
Write factory code that works with both generators:
// Good - works with both
'email' => $this->getGenerator()->email(),
'name' => $this->getGenerator()->name(),
'status' => $this->getGenerator()->enumCase(TestStatus::class),
// Avoid generator-specific methods unless necessary2. Use Configuration for Switching
Don't hardcode generator selection in factories:
// Good - use configuration
Configure::write('FixtureFactories.generatorType', 'dummy');
// Good - per-factory override
ArticleFactory::new()->setGenerator('dummy')->build();
// Good - set global default explicitly
BaseFactory::setDefaultGenerator('dummy');Tip: Leave
FixtureFactories.instanceLevelGeneratorenabled so thatsetGenerator()stays scoped to the current factory instance. See Fixture Factories.
3. Test with Both Generators (Optional)
If your library supports multiple PHP versions, test with both:
# .github/workflows/ci.yml
matrix:
php: ['8.2', '8.3', '8.4']
generator: ['faker', 'dummy']
exclude:
- php: '8.2'
generator: 'dummy'4. Seed for Reproducible Tests
Factories are seeded with 1234 by default for reproducible data, combined with the factory class name so two factories do not start on the same sequence. You can configure a different seed globally:
// In tests/bootstrap.php or config/app.php
Configure::write('FixtureFactories.seed', 9999);See config/app.example.php in this plugin for all available configuration options.
Feature Matrix
| Feature | Faker | DummyGenerator |
|---|---|---|
| Basic data types | ✅ | ✅ |
| Text generation | ✅ | ✅ |
| Date/time | ✅ | ✅ |
| Internet (email, URL) | ✅ | ✅ |
| Person (name, title) | ✅ | ✅ |
| Address | ✅ | ✅ |
| Phone numbers | ✅ | ✅ |
| Company | ✅ | ✅ |
| UUID | ✅ | ✅ |
| Colors | ✅ | ✅ |
| Credit cards | ✅ | ✅ |
| Barcodes (EAN, ISBN) | ✅ | ✅ |
| Locale support | ✅ Full | Not used by the adapter |
| Native enum support | ⚠️ Shimmed | ✅ Native |
unique() modifier | ✅ | ✅ |
optional() modifier | ✅ | ✅ |
| Seeding | ✅ | ✅ |
| Minimum PHP version | 8.2+ | 8.3+ |
Troubleshooting
"Class not found" errors
Faker not found:
Faker library is not installed. Please install it using: `composer require --dev fakerphp/faker`DummyGenerator not found:
DummyGenerator library is not installed. Please install it using: `composer require --dev johnykvsky/dummygenerator`Solution: Install the required package.
Method not found
Problem: A method works with one generator but not the other
Solution: Check the compatibility table above. Most methods are shimmed, but some advanced features may differ.
Additional Resources
FAQ
Which generator should I use?
- Use Faker if you need extensive locale support or need to support PHP < 8.3
- Use DummyGenerator if you're on PHP 8.3+ and want a modern, lean solution with native enum support
Can I use both generators in the same project?
Yes! You can configure different generators per-factory or switch globally. However, it's recommended to use one consistently for maintainability.
Will my existing factories break if I switch?
Most likely not. The plugin provides compatibility shims for common methods. However, test your factories after switching.
How do I contribute new methods?
Add them to GeneratorInterface and implement in both FakerAdapter and DummyGeneratorAdapter, ensuring compatibility across both generators.
Can I create a custom generator?
Yes! Implement GeneratorInterface and register it:
use CakephpFixtureFactories\Generator\CakeGeneratorFactory;
CakeGeneratorFactory::registerAdapter('custom', MyCustomAdapter::class);
Configure::write('FixtureFactories.generatorType', 'custom');