appventus/datamigration-bundle
Installation:
composer require appventus/datamigration-bundle
Register the bundle in config/bundles.php:
AppVentus\DataMigrationBundle\AppVentusDataMigrationBundle::class => ['all' => true],
Enable Tracking:
Add the DataMigrationListener to your Doctrine event manager in config/packages/doctrine.yaml:
doctrine:
orm:
event_listeners:
AppVentus\DataMigrationBundle\EventListener\DataMigrationListener: ~
First Use Case:
php bin/console appventus:datamigration:generate
migrations/20240101000000_EntityMigration.php) to version control.migrations/ (default path). Inspect these to understand recorded operations.Record Changes:
Article entities).Generate Migration:
php bin/console appventus:datamigration:generate
migrations/20240101000000_ArticleMigration.php) with serialized operations.Share and Apply:
php bin/console appventus:datamigration:migrate
Seed Data:
DataSeeder class).$user = new User();
$user->name = 'Test User';
$entityManager->persist($user);
$entityManager->flush();
Capture Changes:
User creation in its internal log.Generate and Reuse:
php bin/console appventus:datamigration:generate
Custom Entities:
@ORM\ExcludeFromDataMigration or configuring the listener:
# config/packages/appventus_data_migration.yaml
appventus_data_migration:
excluded_entities:
- App\Entity\ExcludedEntity
Post-Processing:
MigrationFileGeneratorInterface:
class CustomMigrationGenerator implements MigrationFileGeneratorInterface {
public function generate(MigrationData $data): string {
// Custom logic (e.g., add timestamps or metadata)
return $this->renderTemplate($data);
}
}
services.yaml:
AppVentus\DataMigrationBundle\MigrationFileGeneratorInterface: '@custom_migration_generator'
Batch Processing:
--batch-size option to split migrations:
php bin/console appventus:datamigration:generate --batch-size=50
Entity State Conflicts:
flush() calls to separate logical operations.Circular References:
ObjectManager. Complex object graphs (e.g., bidirectional associations) may cause serialization issues. Test with:
php bin/console appventus:datamigration:validate
Database Schema Mismatches:
php bin/console doctrine:schema:validate
Performance Overhead:
$this->get('appventus_data_migration.listener')->disableTracking();
// Perform bulk operations...
$this->get('appventus_data_migration.listener')->enableTracking();
Log Level:
config/packages/dev/appventus_data_migration.yaml:
appventus_data_migration:
debug: true
bin/console debug:container appventus_data_migration.logger
Dry Runs:
php bin/console appventus:datamigration:migrate --dry-run
Migration File Inspection:
// Example generated migration:
$this->create('App\Entity\User', [
'id' => 1,
'name' => 'Test User',
'email' => 'test@example.com',
]);
Default Migration Path:
migrations/ directory in config/packages/appventus_data_migration.yaml:
appventus_data_migration:
migration_directory: '%kernel.project_dir%/custom/migrations'
File Naming:
YYYYMMDDHHmmss_EntityNameMigration.php. Customize the timestamp format via:
appventus_data_migration:
timestamp_format: 'YmdHis'
Dependency on ShortcutsBundle:
appventus/shortcuts-bundle. Install it explicitly if missing:
composer require appventus/shortcuts-bundle:dev-master
Custom Migration Classes:
services:
AppVentus\DataMigrationBundle\Migration\MigrationInterface: '@custom_migration_class'
Pre/Post-Migration Hooks:
MigrationEventSubscriber to add logic before/after migration:
class CustomMigrationSubscriber implements MigrationEventSubscriber {
public function onPreMigrate(MigrationEvent $event) {
// Add pre-migration logic (e.g., backups)
}
}
services.yaml:
AppVentus\DataMigrationBundle\Event\MigrationEventSubscriberInterface: ['@custom_migration_subscriber', 'onPreMigrate']
Data Transformation:
MigrationDataTransformerInterface to modify recorded data before migration:
class EmailObfuscatorTransformer implements MigrationDataTransformerInterface {
public function transform(MigrationData $data) {
foreach ($data->getEntities() as $entity) {
if ($entity instanceof User) {
$entity->email = 'obfuscated@example.com';
}
}
return $data;
}
}
How can I help you explore Laravel packages today?