Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Doktrin 2:Wie man ein One-to-Many in ein Many-to-Many umwandelt, ohne Daten zu verlieren

OK, ich habe tatsächlich einen Weg gefunden, Doktrinenmigrationen zu verwenden.

Ich habe zuerst sichergestellt, dass meine Änderungen korrekt gesetzt wurden, indem ich ein Doktrin:Schema:Update --Force verwendet, den Profiler überprüft und dann zur letzten Datenbank zurückgekehrt bin.

Verwenden Sie also das Doktrinenmigrationspaket:

doctrine:migrations:diff

erstellt eine neue Migrationsklasse

Bearbeiten Sie die Klasse, um sie Ihren Bedürfnissen anzupassen. Meins war :

<?php

namespace Application\Migrations;

use AppBundle\Entity\Core\Media;
use AppBundle\Entity\FoodAnalytics\Recipe;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Auto-generated Migration: Please modify to your needs!
 */
class Version20150525154902 extends AbstractMigration implements ContainerAwareInterface
{

    private $customSQL = array();

    /** @var Container */
    private $container;


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

    /**
     * @param Schema $schema
     */
    public function preUp(Schema $schema)
    {
        $query = "SELECT id as mediaId, recipeId FROM `media` WHERE recipeId IS NOT NULL";
        $data = $this->connection->prepare($query);
        $data->execute();
        foreach ($data as $row)
        {
            $mediaId = $row['mediaId'];
            $recipeId = $row['recipeId'];
            $this->customSQL[] = "($mediaId, $recipeId)";
        }

    }

    /**
     * @param Schema $schema
     */
    public function up(Schema $schema)
    {
        // this up() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('CREATE TABLE media_recipes (mediaId INT UNSIGNED NOT NULL, recipeId INT UNSIGNED NOT NULL, INDEX IDX_C2BE64FC27D9F5AC (mediaId), INDEX IDX_C2BE64FC6DCBA54 (recipeId), PRIMARY KEY(mediaId, recipeId)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
        $this->addSql('ALTER TABLE media_recipes ADD CONSTRAINT FK_C2BE64FC27D9F5AC FOREIGN KEY (mediaId) REFERENCES media (id) ON DELETE CASCADE');
        $this->addSql('ALTER TABLE media_recipes ADD CONSTRAINT FK_C2BE64FC6DCBA54 FOREIGN KEY (recipeId) REFERENCES Recipe (id) ON DELETE CASCADE');
        $this->addSql('ALTER TABLE media DROP FOREIGN KEY FK_6A2CA10C6DCBA54');
        $this->addSql('DROP INDEX IDX_6A2CA10C6DCBA54 ON media');
        $this->addSql('ALTER TABLE media DROP recipeId');
        $this->addSql('ALTER TABLE recipe ADD versionDetails VARCHAR(200) DEFAULT NULL');

    }

    public function postUp(Schema $schema)
    {
        $SQL = 'INSERT INTO media_recipes (mediaId, recipeId) VALUES ' . implode(', ', $this->customSQL);

        $this->connection->executeQuery($SQL);
    }



    /**
     * @param Schema $schema
     */
    public function down(Schema $schema)
    {
        // this down() migration is auto-generated, please modify it to your needs
        $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');

        $this->addSql('DROP TABLE media_recipes');
        $this->addSql('ALTER TABLE media ADD recipeId INT UNSIGNED DEFAULT NULL');
        $this->addSql('ALTER TABLE media ADD CONSTRAINT FK_6A2CA10C6DCBA54 FOREIGN KEY (recipeId) REFERENCES recipe (id) ON DELETE CASCADE');
        $this->addSql('CREATE INDEX IDX_6A2CA10C6DCBA54 ON media (recipeId)');
    }
}

Führen Sie dann das Update durch :

doctrine:migrations:migrate

und bestätigen y