Installation:
composer require dakatsuka/blueprint-bundle:^1.1.0
Register the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3.x) under dev/test environments.
First Blueprint:
Create a PHP file in src/YourBundle/Tests/Blueprints/post.php:
use Dakatsuka\BlueprintBundle\Blueprint;
Blueprint::register('post', 'App\Entity\Post', function ($post, $blueprint) {
$post->setTitle('Default Title');
$post->setBody('Default Body');
});
First Usage:
In a test case, inject the blueprint service and create an entity:
$post = $this->get('blueprint')->create('post');
$this->assertInstanceOf('App\Entity\Post', $post);
src/YourBundle/Tests/Blueprints/ (convention).blueprint service is auto-registered.Blueprint::register() method signature.Define Blueprints:
Register blueprints in dedicated files (e.g., user.php, product.php) under Tests/Blueprints/.
Use the $blueprint object to:
$blueprint->sequence()).$blueprint->create('related_blueprint')).$blueprint->get('service_id')).Example:
Blueprint::register('user', 'App\Entity\User', function ($user, $blueprint) {
$user->setEmail('user' . $blueprint->sequence() . '@example.com');
$user->setPosts($blueprint->createMany('post', 3)); // Create 3 posts
});
Test Setup:
Use the blueprint service in setUp() to preload test data:
public function setUp(): void {
$this->user = $this->get('blueprint')->create('user');
$this->post = $this->get('blueprint')->create('post', ['title' => 'Custom Title']);
}
Dynamic Data:
Pass overrides as the second argument to create():
$post = $this->get('blueprint')->create('post', ['title' => 'Dynamic Title']);
dev/test environments to avoid runtime overhead.blueprint service directly into test classes or use the container:
$this->blueprint = self::$container->get('blueprint');
Circular Dependencies:
Avoid bidirectional blueprint references (e.g., A creates B, B creates A). Use lazy loading or separate blueprints for complex hierarchies.
// Anti-pattern (risk of infinite recursion)
Blueprint::register('a', 'App\Entity\A', function ($a, $blueprint) {
$a->setB($blueprint->create('b')); // 'b' might try to create 'a'
});
Sequence Collisions: Sequences are global per test run. Reset them manually if needed:
$this->get('blueprint')->resetSequence('post');
Entity Manager Flush: Blueprints do not auto-flush the EM. Manually flush after creation if needed:
$post = $this->get('blueprint')->create('post');
$this->get('doctrine')->getManager()->flush();
Namespace Conflicts:
Ensure blueprint class namespaces match the bundle structure (e.g., Acme\BlogBundle\Tests\Blueprints\post.php for Acme\BlogBundle).
Tests/Blueprints/ directory and is auto-loaded (Symfony’s autoloader).Blueprint::register() matches the actual entity class.var_dump($blueprint->sequence()) to debug sequence generation.Custom Sequence Generators: Extend the bundle by overriding the sequence logic:
$blueprint->setSequenceGenerator('post', function () {
return uniqid();
});
Post-Creation Callbacks:
Use the $blueprint object’s afterCreate callback (if supported in newer versions) or wrap creation in a closure:
$post = $this->get('blueprint')->create('post');
$post->setSlug($this->generateSlug($post->getTitle()));
Bulk Operations:
Combine with createMany() for batch creation:
$users = $this->get('blueprint')->createMany('user', 10);
bundles.php.How can I help you explore Laravel packages today?