ترحيلات قاعدة البيانات
نظرة عامة
Section titled “نظرة عامة”توفر ترحيلات قاعدة البيانات تغييرات قابلة للإرجاع والمراقبة بالإصدار على المخطط. تضمن حالات قاعدة البيانات المتسقة عبر بيئات التطوير والتدرج والإنتاج.
هيكل الترحيل
Section titled “هيكل الترحيل”تسمية الملفات
Section titled “تسمية الملفات”migrations/├── 001_create_articles_table.php├── 002_add_status_column.php├── 003_create_categories_table.php├── 004_add_indexes.php└── 005_add_foreign_keys.phpفئة الترحيل
Section titled “فئة الترحيل”<?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', `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}`"); }};العمليات الشائعة
Section titled “العمليات الشائعة”إضافة أعمدة
Section titled “إضافة أعمدة”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// أضف عمود واحد $db->queryF("ALTER TABLE `{$table}` ADD COLUMN `views` INT UNSIGNED DEFAULT 0 AFTER `status`");
// أضف أعمدة متعددة $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`");}تعديل الأعمدة
Section titled “تعديل الأعمدة”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// تغيير نوع العمود $db->queryF("ALTER TABLE `{$table}` MODIFY COLUMN `title` VARCHAR(500) NOT NULL");
// إعادة تسمية العمود $db->queryF("ALTER TABLE `{$table}` CHANGE `summary` `excerpt` TEXT");}إضافة الفهارس
Section titled “إضافة الفهارس”public function up(\XoopsDatabase $db): void{ $table = $db->prefix('mymodule_articles');
// فهرس عمود واحد $db->queryF("CREATE INDEX `idx_created` ON `{$table}` (`created_at`)");
// فهرس مركب $db->queryF("CREATE INDEX `idx_status_date` ON `{$table}` (`status`, `created_at`)");
// فهرس فريد $db->queryF("CREATE UNIQUE INDEX `idx_slug` ON `{$table}` (`slug`)");
// فهرس النص الكامل $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}`");}المفاتيح الأجنبية
Section titled “المفاتيح الأجنبية”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`");}متعقب الترحيل
Section titled “متعقب الترحيل”تشغيل الترحيلات
Section titled “تشغيل الترحيلات”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; }}فئة متعقب الترحيل
Section titled “فئة متعقب الترحيل”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] ); } }}أفضل الممارسات
Section titled “أفضل الممارسات”- تغيير واحد لكل ترحيل - حافظ على الترحيلات مركزة
- اكتب طرق Down دائماً - تمكين الاسترجاع
- اختبر كلا الاتجاهين - تحقق من up() و down()
- استخدم المعاملات - غلف الترحيلات المعقدة
- لا تعديل الترحيلات القديمة - أنشئ جديد بدلاً من ذلك
- دعم احتياطي قبل التشغيل - خاصة في الإنتاج
الوثائق ذات الصلة
Section titled “الوثائق ذات الصلة”- Database-Schema - تصميم المخطط
- Database-Operations - تنفيذ الاستعلام
- ../xoops_version.php - بيان الوحدة
- ../../07-XOOPS-4.0/XOOPS-4.0-Architecture - العمارة الحديثة