doesntmattr/mongodb-migrations-bundle
Symfony bundle that integrates the doesntmattr MongoDB Migrations library, providing configuration and tooling to run MongoDB schema/data migrations in Symfony apps. Supports PHP 5.6 via v1.x and PHP 7.1+ via v3.x.
Since Laravel uses Symfony components under the hood, this bundle can be adapted with minimal effort. Start by:
Install the Bundle Add the package via Composer (choose version based on PHP support):
composer require doesntmattr/mongodb-migrations-bundle
Register the Bundle
In config/app.php, add the bundle to the extra.bundles array:
'extra.bundles' => [
// ...
AntiMattr\Bundle\MongoDBMigrationsBundle\MongoDBMigrationsBundle::class,
],
Configure Migrations
Add MongoDB migration settings to config/services.php (Symfony-style config):
'mongo_db_migrations' => [
'collection_name' => 'migration_versions',
'database_name' => env('DB_DATABASE', 'laravel'),
'dir_name' => database_path('migrations/mongodb'),
'script_dir_name' => null, // Optional: For custom scripts
'name' => 'Laravel MongoDB Migrations',
'namespace' => 'App\\Database\\Migrations\\MongoDB',
],
Publish Assets (Optional) Publish the bundle’s config and migrations:
php artisan vendor:publish --provider="AntiMattr\Bundle\MongoDBMigrationsBundle\MongoDBMigrationsBundle" --tag="config"
Generate First Migration Run the console command to scaffold a migration:
php artisan mongodb:migrations:generate
This creates a timestamped migration class in database/migrations/mongodb/.
Use this bundle to:
Example migration (VersionYYYYMMDDHHMMSS):
use AntiMattr\MongoDBMigrations\AbstractMigration;
use MongoDB\Driver\Manager;
class Version20231001000000 extends AbstractMigration
{
public function up(Manager $manager)
{
$db = $manager->selectDatabase($this->getDatabaseName());
$collection = $db->selectCollection('users');
// Add an index
$collection->createIndex(['email' => 1], ['unique' => true]);
// Transform documents
$bulk = new \MongoDB\Driver\BulkWrite;
$bulk->update(
['status' => 'active'],
['$set' => ['last_updated' => new \MongoDB\BSON\UTCDateTime()]]
);
$collection->executeBulkWrite($bulk);
}
}
Run migrations:
php artisan mongodb:migrations:migrate
mongodb:migrations:generate to create new migration files.mongodb:migrations:migrate --env=local to test changes.mongodb:migrations:version --delete <timestamp> to revert a migration (without re-running logic).mongodb:migrations:migrate as a post-deploy step in your pipeline.mongodb:migrations:execute --replay to safely re-run migrations.up() to validate data before changes:
public function up(Manager $manager)
{
$collection = $manager->selectDatabase($this->getDatabaseName())->selectCollection('users');
$count = $collection->countDocuments(['email' => null]);
if ($count > 0) {
throw new \RuntimeException("Cannot migrate: Users with null emails exist.");
}
// Proceed with migration...
}
postUp() for cleanup or notifications:
public function postUp(Manager $manager)
{
// Log migration completion
\Log::info("Migration completed at " . now());
}
Service Container Access
Implement ContainerAwareInterface to use Laravel services (e.g., Cache, Queue):
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Version20231001000000 extends AbstractMigration implements ContainerAwareInterface
{
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function up(Manager $manager)
{
$cache = $this->container->get('cache');
$cache->put('migration_ran_at', now());
// ...
}
}
Environment-Aware Migrations Use Laravel’s environment variables in migrations:
public function up(Manager $manager)
{
$dbName = config('mongo_db_migrations.database_name');
if (app()->environment('production')) {
$dbName .= '_prod';
}
$db = $manager->selectDatabase($dbName);
// ...
}
Artisan Command Aliases Create Laravel-specific console commands to wrap bundle commands:
// app/Console/Commands/MigrateMongo.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Application;
class MigrateMongo extends Command
{
protected $signature = 'mongo:migrate';
protected $description = 'Run MongoDB migrations';
public function handle()
{
$application = new Application();
$application->add(new \AntiMattr\Bundle\MongoDBMigrationsBundle\Command\MigrateCommand());
$application->run(new \Symfony\Component\Console\Input\ArrayInput([
'command' => 'mongodb:migrations:migrate',
]));
}
}
Register the command in app/Console/Kernel.php:
protected $commands = [
Commands\MigrateMongo::class,
];
Event Listeners Trigger Laravel events after migrations:
// In a service provider
public function boot()
{
\AntiMattr\Bundle\MongoDBMigrationsBundle\Event\MigrationExecuted::subscribe(function ($event) {
event(new \App\Events\MongoMigrationRan($event->getMigration()));
});
}
Namespace Conflicts
App\Migrations vs. App\Database\Migrations), the bundle may fail to autoload migrations.namespace in config matches the actual directory structure. Example:
config/mongo_db_migrations.namespace = App\Database\Migrations\MongoDB
database/migrations/mongodb/Version*.php
PHP 7.1+ Requirements
^3.0 branch requires PHP 7.1+. Using it on PHP 5.6 will fail.^1.0 for older PHP versions or upgrade your environment.Doctrine ODM Dependency
ContainerAwareInterface with doctrine.odm.default_document_manager.$dm = $this->container->has('doctrine.odm.default_document_manager')
? $this->container->get('doctrine.odm.default_document_manager')
: null;
Migration Ordering
FixUsers.php) may break ordering.Version20231001000000.php).Cursor Timeouts
$collection->find([], ['timeout' => false])->limit(-1); // No timeout
Or pass options to the update method:
$bulk->update([], ['$set' => [...]], ['socketTimeoutMS' => 0]);
--dry-run to preview changes without executing:
php artisan mongodb:migrations:migrate --dry-run
How can I help you explore Laravel packages today?