Di chuyển cơ sở dữ liệu
Tổng quan
Phần tiêu đề “Tổng quan”Di chuyển cơ sở dữ liệu cung cấp các thay đổi có thể đảo ngược, được kiểm soát theo phiên bản đối với lược đồ cơ sở dữ liệu của bạn. Chúng đảm bảo trạng thái cơ sở dữ liệu nhất quán trong các môi trường phát triển, dàn dựng và sản xuất.
Cấu trúc di chuyển
Phần tiêu đề “Cấu trúc di chuyển”Đặt tên tệp
Phần tiêu đề “Đặt tên tệp”migrations/├── 001_create_articles_table.php├── 002_add_status_column.php├── 003_create_categories_table.php├── 004_add_indexes.php└── 005_add_foreign_keys.phpLớp di chuyển
Phần tiêu đề “Lớp di chuyển”<?phpdeclare(strict_types=1);
return new class { public function up(\XoopsDatabase $db): void { $table = $db->prefix('mymodule_articles');
$sql = "CREATE TABLE IF NOT EXISTS `{$table}` ( `id` VARCHAR(26) NOT NULL COMMENT 'ULID identifier', `title` VARCHAR(255) NOT NULL, `content` MEDIUMTEXT, `status` ENUM('draft', 'published', 'archived') DEFAULT 'draft', `author_id` INT UNSIGNED NOT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_status` (`status`), KEY `idx_author` (`author_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$db->queryF($sql); }
public function down(\XoopsDatabase $db): void { $table = $db->prefix('mymodule_articles'); $db->queryF("DROP TABLE IF EXISTS `{$table}`"); }};Hoạt động chung
Phần tiêu đề “Hoạt động chung”Thêm cột
Phần tiêu đề “Thêm cột”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// Add single column $db->queryF("ALTER TABLE `{$table}` ADD COLUMN `views` INT UNSIGNED DEFAULT 0 AFTER `status`");
// Add multiple columns $db->queryF("ALTER TABLE `{$table}` ADD COLUMN `summary` TEXT AFTER `content`, ADD COLUMN `featured` TINYINT(1) DEFAULT 0 AFTER `views`");}
public function down(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles'); $db->queryF("ALTER TABLE `{$table}` DROP COLUMN `views`, DROP COLUMN `summary`, DROP COLUMN `featured`");}Sửa đổi cột
Phần tiêu đề “Sửa đổi cột”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// Change column type $db->queryF("ALTER TABLE `{$table}` MODIFY COLUMN `title` VARCHAR(500) NOT NULL");
// Rename column $db->queryF("ALTER TABLE `{$table}` CHANGE `summary` `excerpt` TEXT");}Thêm chỉ mục
Phần tiêu đề “Thêm chỉ mục”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// Single column index $db->queryF("CREATE INDEX `idx_created` ON `{$table}` (`created_at`)");
// Composite index $db->queryF("CREATE INDEX `idx_status_date` ON `{$table}` (`status`, `created_at`)");
// Unique index $db->queryF("CREATE UNIQUE INDEX `idx_slug` ON `{$table}` (`slug`)");
// Fulltext index $db->queryF("CREATE FULLTEXT INDEX `idx_search` ON `{$table}` (`title`, `content`)");}
public function down(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles'); $db->queryF("DROP INDEX `idx_created` ON `{$table}`"); $db->queryF("DROP INDEX `idx_status_date` ON `{$table}`"); $db->queryF("DROP INDEX `idx_slug` ON `{$table}`"); $db->queryF("DROP INDEX `idx_search` ON `{$table}`");}Khóa ngoại
Phần tiêu đề “Khóa ngoại”public function up(\XoopsDatabase $db): void{ $articles = $db->prefix('mymodule_articles'); $categories = $db->prefix('mymodule_categories');
$db->queryF("ALTER TABLE `{$articles}` ADD CONSTRAINT `fk_article_category` FOREIGN KEY (`category_id`) REFERENCES `{$categories}` (`id`) ON DELETE SET NULL ON UPDATE CASCADE");}
public function down(\XoopsDatabase $db): void{ $articles = $db->prefix('mymodule_articles'); $db->queryF("ALTER TABLE `{$articles}` DROP FOREIGN KEY `fk_article_category`");}Người chạy di chuyển
Phần tiêu đề “Người chạy di chuyển”Đang chạy di chuyển
Phần tiêu đề “Đang chạy di chuyển”function xoops_module_update_mymodule(\XoopsModule $module, $previousVersion){ $db = \XoopsDatabaseFactory::getDatabaseConnection(); $migrator = new MigrationRunner($db, $module->dirname());
try { $migrator->migrate(); return true; } catch (\Exception $e) { $module->setErrors($e->getMessage()); return false; }}Lớp Á quân di chuyển
Phần tiêu đề “Lớp Á quân di chuyển”class MigrationRunner{ private string $migrationsPath; private string $table;
public function __construct( private \XoopsDatabase $db, private string $moduleName ) { $this->migrationsPath = XOOPS_ROOT_PATH . "/modules/{$moduleName}/migrations"; $this->table = $db->prefix("{$moduleName}_migrations"); }
public function migrate(): void { $this->createMigrationsTable(); $executed = $this->getExecutedMigrations();
foreach ($this->getPendingMigrations($executed) as $file) { $this->runMigration($file); } }
private function runMigration(string $file): void { $migration = require $this->migrationsPath . '/' . $file; $migration->up($this->db);
$this->db->queryF( "INSERT INTO `{$this->table}` (migration, executed_at) VALUES (?, NOW())", [$file] ); }
public function rollback(int $steps = 1): void { $migrations = $this->getExecutedMigrations(); $toRollback = array_slice(array_reverse($migrations), 0, $steps);
foreach ($toRollback as $file) { $migration = require $this->migrationsPath . '/' . $file; $migration->down($this->db);
$this->db->queryF( "DELETE FROM `{$this->table}` WHERE migration = ?", [$file] ); } }}Các phương pháp hay nhất
Phần tiêu đề “Các phương pháp hay nhất”- Một thay đổi cho mỗi lần di chuyển - Giữ việc di chuyển tập trung
- Luôn viết ra các phương pháp - Cho phép khôi phục
- Kiểm tra cả hai hướng - Xác minh up() và down()
- Sử dụng Giao dịch - Bao gồm các quá trình di chuyển phức tạp
- Không sửa đổi di chuyển cũ - Thay vào đó hãy tạo di chuyển mới
- Sao lưu trước khi chạy - Đặc biệt trong sản xuất
Tài liệu liên quan
Phần tiêu đề “Tài liệu liên quan”- Cơ sở dữ liệu-Lược đồ - Thiết kế lược đồ
- Hoạt động cơ sở dữ liệu - Thực hiện truy vấn
- ../xoops_version.php - Bản kê khai mô-đun
- ../../07-XOOPS-4.0/XOOPS-4.0-Architecture - Kiến trúc hiện đại