Search code examples
phpsymfonydoctrinedatabase-migration

Making a Doctrine migration adhere to ContainerAwareInterface


I have a Doctrine migration that looks like this:

<?php

namespace Application\Migrations;

use Doctrine\ORM\Mapping\PushNotification;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Doctrine\DBAL\Schema\Schema;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
class Version20180123103147 extends AbstractMigration implements ContainerAwareInterface
{
    private $container;

    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
     * @param Schema $schema
     */
    public function up(Schema $schema)
    {
        $em = $this->container->getDoctrine()->getManager();
        $tableName = $em->getClassMetadata('AppBundle:PushNotification')->getTableName();

        $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('ALTER TABLE '.$tableName.' ADD COLUMN   last_offset int(11) ');
        $this->addSql('ALTER TABLE '.$tableName.' ADD COLUMN   failure_count int(11) ');
        $this->addSql('ALTER TABLE '.$tableName.' ADD COLUMN   is_sent int(11) ');
        $this->addSql('ALTER TABLE '.$tableName.' ADD COLUMN   send_date datetime ');


    }

    /**
     * @param Schema $schema
     */
    public function down(Schema $schema)
    {

        $em = $this->container->getDoctrine()->getManager();
        $tableName = $em->getClassMetadata('AppBundle:PushNotification')->getTableName();

        $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('ALTER TABLE '.$tableName.' DROP COLUMN   last_offset ');
        $this->addSql('ALTER TABLE '.$tableName.' DROP COLUMN   failure_count ');
        $this->addSql('ALTER TABLE '.$tableName.' DROP COLUMN   is_sent ');
        $this->addSql('ALTER TABLE '.$tableName.' DROP COLUMN   send_date ');

    }
}

... and when running migrations, I get an error stating Declaration of Application\Migrations\Version20180123103147::setContainer() must be compatible with Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer(Symfony\Component\DependencyInjection\ContainerInterface $container = NULL)

This error seems out of place since I copied the method signature directly from the interface in question.

Is there an obvious bit of code that I'm missing here?


Solution

  • It seems you are trying to inject the container into another service, this is generally highly discouraged. Rather, you can inject the EntityManagerInterface and use that.

    However, I do see this is a migration file. There are no reasons in your given code why this should be here, rather just hard-code the table name like this:

    $this->addSql('ALTER TABLE push_notification ADD COLUMN  last_offset int(11)');
    

    So a summary, the reason you are receiving that error, is because the migration is expecting an instance of the container to be passed to your migration, this, however, never occurs since you did not register the migration as a service.

    (sidenote: never register a migration as a service)