Таким образом, я совершил кучу миграции Doctrine2 (https://github.com/doctrine/migrations), но у меня возник вопрос о новой миграции, которую я пытаюсь сделать.
Я немного $this->addSql()
в библиотеку, и я вижу, что $this->addSql()
используется для создания списка SQL для выполнения, а затем он запускается позже.
Я хотел сделать что-то там, где я выбираю некоторые данные, перебираю строки, вставляю на них новые данные и удаляю выбранные данные. Это довольно легко поддается библиотеке DBAL, но мне интересно, могу ли я безопасно использовать protected $connection
в миграции? Или это плохо, потому что он выполнял бы инструкции до того, как какой-либо из моих $this->addSql()
SQL будет выполнен? Также кажется, что это сломало бы настройку dry-run
режима из того, что я видел в коде. Имеет ли кто-либо опыт такого рода миграции? Есть ли лучшие практики?
Ниже приведена миграция, которую я хочу сделать, но я не уверен, что это поддерживается Doctrine Migrations:
public function up(Schema $schema) { // this up() migration is autogenerated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); $this->addSql("ALTER TABLE article_enclosures ADD is_scrape TINYINT(1) NOT NULL"); $this->addSql("ALTER TABLE images DROP FOREIGN KEY FK_E01FBE6AA536AAC7"); // now lets take all images with a scrape and convert the scrape to an enclosure // // Select all images where not scrape_id is null (join on article_image_scrape) // for each image: // insert into article_enclosures // update image set enclosure_id = new ID // delete from article_image_scrape where id... // // insert into article_enclosures select article_image_scrapes... $sql = "SELECT i.id img_id, e.* FROM images i JOIN article_image_scrapes e ON i.scrape_id = e.id"; $stmt = $this->connection->prepare($sql); $stmt->execute(); $scrapesToDelete = array(); while ($row = $stmt->fetch()) { $scrapeArticle = $row['article_id']; $scrapeOldId = $row['id']; $scrapeUrl = $row['url']; $scrapeExtension = $row['extension']; $scrapeUrlHash = $row['url_hash']; $imageId = $row['image_id']; $this->connection->insert('article_enclosures', array( 'url' => $scrapeUrl, 'extension' => $scrapeExtension, 'url_hash' => $scrapeUrlHash )); $scrapeNewId = $this->connection->lastInsertId(); $this->connection->update('images', array( 'enclosure_id' => $scrapeNewId, 'scrape_id' => null ), array( 'id' => $imageId )); $scrapesToDelete[] = $scrapeOldId; } foreach ($scrapesToDelete as $id) { $this->connection->delete('article_image_scrapes', array('id' => $id)); } $this->addSql("INSERT INTO article_scrapes (article_id, url, extension, url_hash) " ."SELECT s.id, s.url, s.extension, s.url_hash" ."FROM article_image_scrapes s"); $this->addSql("DROP INDEX IDX_E01FBE6AA536AAC7 ON images"); $this->addSql("ALTER TABLE images DROP scrape_id, CHANGE enclosure_id enclosure_id INT NOT NULL"); }
Вы можете использовать $connection
как это
$result = $this->connection->fetchAssoc('SELECT id, name FROM table1 WHERE id = 1'); $this->abortIf(!$result, 'row with id not found'); $this->abortIf($result['name'] != 'jo', 'id 1 is not jo'); // etc..
Вы должны только читать базу данных, а не использовать соединение, чтобы сделать обновление / удаление, чтобы он не нарушил вариант сухого хода.
В вашем примере вам нужно выполнить две миграции. Первый будет делать две таблицы alter. Второй будет выполнять «изображения со скрипом и конвертировать процедуру очистки в оболочку». С помощью множественной миграции легче вернуть их, если что-то пойдет не так.
FYI, последние документы показывают этот пример, который еще лучше с методом postUp
http://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html
// ... use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; class Version20130326212938 extends AbstractMigration implements ContainerAwareInterface { private $container; public function setContainer(ContainerInterface $container = null) { $this->container = $container; } public function up(Schema $schema) { // ... migration content } public function postUp(Schema $schema) { $em = $this->container->get('doctrine.orm.entity_manager'); // ... update the entities } }