Vì vậy, tôi đã thực hiện một loạt các di chuyển Doctrine2 (https://github.com/doctrine/migrations) nhưng tôi có một câu hỏi cho một di cư mới tôi đang cố gắng làm.
Tôi đã đào sâu vào thư viện một chút và tôi thấy rằng $this->addSql()
được sử dụng để xây dựng danh sách SQL để thực thi và sau đó nó được thực thi sau này.
Tôi muốn làm điều gì đó mà tôi chọn một số dữ liệu, lặp qua các hàng, chèn dữ liệu mới dựa trên đó, sau đó xóa dữ liệu tôi đã chọn. Điều này cho chính nó đến thư viện DBAL khá dễ dàng, nhưng tôi tự hỏi, tôi có thể sử dụng số protected $connection
khi di chuyển một cách an toàn không? Hoặc là xấu bởi vì nó sẽ thực hiện các câu lệnh trước khi bất kỳ SQL nào của tôi $this->addSql()
được thực thi? Ngoài ra, có vẻ như điều này sẽ phá vỡ cài đặt dry-run
từ những gì tôi đã thấy trong mã. Có ai có kinh nghiệm với loại di cư này không? Có bất kỳ thực hành tốt nhất nào không?
Sau đây là cuộc di cư Tôi muốn làm, nhưng tôi không tự tin rằng đây được hỗ trợ bởi Học thuyết 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");
}
tôi quyết định chỉ làm di cư riêng biệt trước và sau khi trang này với cần thiết 'addSql' cuộc gọi để việc đặt hàng là chính xác. – Matt
Bạn đã thử chưa? Có vẻ ok với tôi – eddy147
Tôi nghĩ vậy, nhưng đây là một năm trước. Tôi tin rằng vấn đề ban đầu vẫn đứng vững. Tức là, bằng cách sử dụng các cuộc gọi '-> addSql()', những cuộc gọi đó sẽ được thực thi cuối cùng. Và 'dry-run' sẽ vẫn chạy thao tác trực tiếp của bạn. Vì vậy, nó vẫn có vẻ hacky (nhưng tôi có thể sai, không bao giờ nhận được một câu trả lời và tôi không nhớ nhiều về điều này nữa). – Matt