Sau một vài lần thử giải pháp quá kỹ thuật và quá thông minh, tôi nghĩ rằng cách giải quyết sau đây là khả thi cho vấn đề.
tl; dr:
- Thúc đẩy quá trình di chuyển ở một trong hai phía của (các) di chuyển xây dựng lược đồ từ con số không.
- Cập nhật dự án.
- Di cư.
- Xóa liên kết và tất cả các lần di chuyển trước đó.
- Xóa các bản ghi khỏi
migrations
bàn.
Bookend đầu tiên đổi tên các bảng bị ảnh hưởng. Bookend thứ hai sao chép dữ liệu từ các bảng đã đổi tên sang các bảng mới, sau đó xóa các bảng đã đổi tên.
Lưu ý:Bạn có thể làm bất cứ điều gì bạn thích bên trong bookends, đây chỉ là mức tối thiểu.
Vì vậy, giả sử bạn điều gì đó tương tự như sau cho việc di chuyển:
- 2017_09_05_000000_create_some_table.php
- 2017_09_05_000001_add_field_x_to_some_table.php
- 2017_09_05_000002_add_field_y_to_some_table.php
- 2017_09_05_000003_add_field_z_to_some_table.php
Chúng tôi sẽ tạo một quá trình di chuyển khác:
- 2017_09_05_000004_pre_refresh.php
Chúng tôi sẽ tạo một quá trình di chuyển khác dựa trên kiến thức hiện có:
- 2017_09_05_000005_create_some_table.php
Chúng tôi sẽ tạo bookend cuối cùng, nơi quá trình di chuyển dữ liệu sẽ diễn ra:
- 2017_09_05_000006_post_refresh.php
Bốn lần di chuyển đầu tiên sẽ không được chạy vì chúng đã được thực hiện.
/** 2017_09_05_000004_pre_refresh.php */
class PreRefresh extends Migration
{
public function up()
{
$prefix = 'zz_';
$tablesToRename = [
'foos',
'bars'
];
foreach($tablesToRename as $table) {
Schema::rename($table, $prefix . $table);
}
}
}
Không cần giảm giá, bởi vì đây là thỏa thuận một lần. Thao tác này sẽ chạy trước, dẫn đến việc đổi tên tất cả các bảng được liệt kê trong mảng. Sau đó, (các) di chuyển tổng hợp (được tối ưu hóa) sẽ chạy.
/** 2017_09_05_000006_post_refresh.php */
class PostRefresh extends Migration
{
public function up()
{
// Do what you need to do.
// If you cannot use your models, just use DB::table() commands.
$foos = DB::table('zz_foos')->get();
foreach ($foos as $foo) {
DB::table('foo')->insert([
'id' => $foo->id,
'created_at' => $foo->created_at,
'updated_at' => $foo->updated_at
]);
}
$bars = DB::table('zz_bars')->get();
foreach ($bars as $bar) {
DB::table('bar')->insert([
'id' => $bar->id,
'created_at' => $bar->created_at,
'updated_at' => $bar->updated_at,
'foo_id' => $bar->foo_id
]);
}
// Tear down.
$prefix = 'zz_';
$tablesToRename = [
'foo',
'bar'
];
foreach ($tablesToRename as $table) {
DB::statement('SET FOREIGN_KEY_CHECKS=0');
Schema::dropIfExists($prefix . $table);
DB::statement('SET FOREIGN_KEY_CHECKS=1');
}
}
}
Sau khi chạy, bạn có thể xóa tất cả di chuyển của mình khỏi pre_refresh
và trước đó. Cũng như post_refresh
. Sau đó, bạn có thể đi vào migrations
bảng và xóa các mục nhập cho những lần di chuyển đó.
Việc xóa các mục nhập là không hoàn toàn cần thiết, nhưng nếu bạn migrate:rollback
bạn sẽ nhận được thông báo lỗi cho biết rằng không thể tìm thấy quá trình di chuyển.
Lưu ý
- Nếu kiến trúc không phải là mô-đun theo thiết kế, nó có thể khá cồng kềnh. Tuy nhiên, nếu bạn đã tách mã của mình thành các dịch vụ thì việc này có vẻ dễ dàng hơn một chút.
- Xử lý lỗi Laravel và thông báo trong quá trình di chuyển rất hạn chế; vì vậy, việc gỡ lỗi có thể khó khăn.
- Thực sự khuyên bạn nên bắt đầu với các bảng ổn định nhất trong ứng dụng / dịch vụ của mình. Hơn nữa, bắt đầu với những điều cơ bản cho ứng dụng của bạn cũng có thể chứng minh là có lợi.
Lưu ý:Khi tôi thực sự làm điều này trong sản xuất, không chỉ tại địa phương của tôi (lặp đi lặp lại) và nếu không có câu trả lời nào tốt hơn, thì tôi sẽ chấp nhận điều này.
Cân nhắc
Nếu bạn đang chia ứng dụng của mình thành các nhà cung cấp dịch vụ bằng cách di chuyển kín đáo, thì bạn có thể nhận xét về nhà cung cấp dịch vụ trong /config/app
khi bạn chạy quá trình di chuyển. Bằng cách này, bạn tạo một lô cho dịch vụ được cơ sở hiện tại. Vì vậy, giả sử bạn có các lần di chuyển sau trong đó mỗi chữ cái đại diện cho một lần di chuyển và mỗi chữ cái trùng lặp đại diện cho cùng một dịch vụ:
- A
- B
- C
- A
- C
- B
- A
Sau khi hợp nhất dịch vụ A:
- B
- C
- C
- B
- A
Sau khi hợp nhất B:
- C
- C
- A
- B
Sau khi hợp nhất C:
- A
- B
- C
cập nhật
54 cuộc di cư xuống còn 27 cuộc cho đến nay. Tôi thậm chí còn kéo ra một số thay đổi Giản đồ từ up()
lớn và down()
và làm cho chúng di chuyển riêng biệt. Tác dụng phụ tốt đẹp ở đây là các lô. Tôi đã di chuyển bắt đầu với các bảng cơ sở mà mọi thứ khác được hỗ trợ trên đó; do đó, quay trở lại là dịch vụ nhiều hơn theo dịch vụ.