Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Container Aware Migration Laravel Package

webignition/container-aware-migration

Container-aware migration support for Laravel packages, letting migrations resolve services and dependencies from the application container instead of relying on hard-coded class instantiation. Useful for packages that need flexible, testable migrations across differing application setups.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a very small utility package, not a bundle. It gives you an abstract Doctrine migration class that is aware of the Symfony service container, so a migration can call application services instead of doing everything through raw SQL.

  1. Install it and inspect what you actually got:

    composer require webignition/container-aware-migration
    

    Open vendor/webignition/container-aware-migration/src/ first. Confirm the base class name/namespace, and check composer.json for its doctrine/migrations, symfony/dependency-injection, and PHP constraints. This package has very low adoption, so verify compatibility before relying on it.

  2. Generate a migration normally, then change it to extend the package’s base class instead of Doctrine\Migrations\AbstractMigration:

    <?php
    
    declare(strict_types=1);
    
    namespace DoctrineMigrations;
    
    use Doctrine\DBAL\Schema\Schema;
    use Webignition\ContainerAwareMigration\ContainerAwareMigration;
    
    final class Version20240101000000 extends ContainerAwareMigration
    {
        public function up(Schema $schema): void
        {
            $service = $this->container->get(MyDataBackfillService::class);
            $service->run();
        }
    
        public function down(Schema $schema): void
        {
            // reverse or no-op
        }
    }
    

    Adjust the namespace/class name to match the package source.

  3. First real use case: a data migration that needs an application service — a repository, slug generator, importer, or API client — that is awkward to reproduce in raw SQL. Use the container only for that service; keep schema changes on $this->connection / DBAL.

If your Symfony/DoctrineMigrationsBundle version does not inject the container into migrations, this package alone will not make it work. In that case use constructor injection through Doctrine migration services or a custom migration factory instead.

Implementation Patterns

  • Use it selectively. Keep ordinary schema migrations extending AbstractMigration. Extend the container-aware class only when the migration genuinely needs a Symfony service.

  • Create an app-level base class. Extend the package class once, add helpers, and make all container-aware migrations extend that:

    abstract class AppMigration extends ContainerAwareMigration
    {
        protected function service(string $id): object
        {
            if ($this->container === null) {
                throw new \LogicException('Container was not injected into migration.');
            }
    
            return $this->container->get($id);
        }
    }
    
  • Fetch services inside up() / down(). Do not store request state or long-lived service references on the migration object. Migrations are instantiated and executed in CLI context.

  • Combine service calls with DBAL. Use the service for business logic, but use $this->connection for direct SQL, schema checks, and bulk operations. This keeps the migration easier to reason about.

  • Make data migrations idempotent. Check whether rows already exist, use deterministic updates, and batch large operations. A migration that calls a service can be re-run accidentally in development.

  • Use it for backfills, not for new application behavior. A good pattern is: read IDs with DBAL, call a service per batch, write results with DBAL. A bad pattern is: call a service that itself performs unpredictable side effects across the whole dataset.

  • Test migrations with a manually injected container. In a kernel test, boot the kernel and call setContainer($container) on the migration before executing it. This catches missing/private service wiring before deployment.

  • Handle generated migrations. doctrine:migrations:diff normally generates a class extending AbstractMigration. Either edit the generated file or add a post-generation step/custom template so it extends your base class.

  • Extension point: override setContainer() in your app base class to add guards or normalize the container type, then expose narrow helper methods such as getRepository() or getService().

Gotchas and Tips

  • Container injection is not automatic by magic. The migration must actually be given the container by the Doctrine migrations command/factory. If $this->container is null, this package is not wired into your current stack. Check your DoctrineMigrationsBundle version and migration factory configuration.
  • Private services will bite you. Modern Symfony services are private by default. $this->container->get(SomeService::class) will throw unless that service is public or exposed through a service locator. Prefer injecting a small public facade/service locator over making many services public.
  • Avoid request-scoped services. request_stack, security tokens, sessions, and similar services are unreliable or unavailable in CLI migrations. Use only stable, stateless services.
  • Old migrations become coupled to current code. If a migration calls a service whose behavior changes later, replaying migrations on a fresh database may produce different data. For critical migrations, freeze the logic in the migration or use raw SQL.
  • Be careful with the EntityManager. Fetching doctrine.orm.entity_manager from the container is tempting, but after a failed flush the EM can be closed. Use DBAL for schema changes and isolate ORM work into small batches with clear().
  • Symfony compatibility matters. ContainerAwareInterface / ContainerAwareTrait have been deprecated or removed across Symfony versions, and this package is tiny and low-activity. Check constraints and pin versions; if it is incompatible, inline the equivalent base class yourself.
  • Debugging checklist: run bin/console doctrine:migrations:status, inspect the migration with bin/console debug:container <service>, execute a single migration in dev, and add an explicit null-container assertion. Do not leave var_dump() debugging in production migrations.
  • The best long-term move may be to copy the pattern. The package is essentially a thin AbstractMigration + ContainerAwareInterface wrapper. If it is unmaintained, create your own three-line base class in your application and remove the dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json