Skip to content

Utiliti Pangkalan Data

Ruang nama XMF\Database menyediakan kelas untuk memudahkan tugas penyelenggaraan pangkalan data yang berkaitan dengan memasang dan mengemas kini modul XOOPS. Utiliti ini mengendalikan migrasi skema, pengubahsuaian jadual dan pemuatan data awal.

Utiliti pangkalan data termasuk:

  • Jadual - Membina dan melaksanakan DDL penyata untuk pengubahsuaian jadual
  • Migrasi - Menyegerakkan skema pangkalan data antara versi modul
  • TableLoad - Memuatkan data awal ke dalam jadual

Kelas Tables memudahkan mencipta dan mengubah suai jadual pangkalan data. Ia membina baris gilir kerja DDL (Bahasa Definisi Data) yang dilaksanakan bersama.

  • Memuatkan skema semasa daripada jadual sedia ada
  • Baris gilir berubah tanpa pelaksanaan segera
  • Mempertimbangkan keadaan semasa semasa menentukan kerja yang perlu dilakukan
  • Mengendalikan awalan jadual XOOPS secara automatik
use Xmf\Database\Tables;
// Create a new Tables instance
$tables = new Tables();
// Load an existing table or start new schema
$tables->addTable('mymodule_items');
// For existing tables only (fails if table doesn't exist)
$tables->useTable('mymodule_items');
$tables = new Tables();
$tables->addTable('mymodule_old_name');
$tables->renameTable('mymodule_old_name', 'mymodule_new_name');
$tables->executeQueue();
$tables->addTable('mymodule_items');
$tables->setTableOptions('mymodule_items', 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4');
$tables->executeQueue();
$tables->addTable('mymodule_temp');
$tables->dropTable('mymodule_temp');
$tables->executeQueue();
// Copy structure only
$tables->copyTable('mymodule_items', 'mymodule_items_backup', false);
// Copy structure and data
$tables->copyTable('mymodule_items', 'mymodule_items_backup', true);
$tables->executeQueue();
$tables = new Tables();
$tables->addTable('mymodule_items');
$tables->addColumn(
'mymodule_items',
'status',
"TINYINT(1) NOT NULL DEFAULT '1'"
);
$tables->executeQueue();
$tables->useTable('mymodule_items');
// Change column attributes
$tables->alterColumn(
'mymodule_items',
'title',
"VARCHAR(255) NOT NULL DEFAULT ''"
);
// Rename and modify column
$tables->alterColumn(
'mymodule_items',
'old_column_name',
"VARCHAR(100) NOT NULL",
'new_column_name'
);
$tables->executeQueue();
$tables->useTable('mymodule_items');
$attributes = $tables->getColumnAttributes('mymodule_items', 'title');
// Returns: "VARCHAR(255) NOT NULL DEFAULT ''"
$tables->useTable('mymodule_items');
$tables->dropColumn('mymodule_items', 'obsolete_field');
$tables->executeQueue();
$tables->useTable('mymodule_items');
$indexes = $tables->getTableIndexes('mymodule_items');
// Returns array like:
// [
// 'PRIMARY' => ['columns' => 'item_id', 'unique' => true],
// 'idx_category' => ['columns' => 'category_id', 'unique' => false]
// ]
$tables->addTable('mymodule_items');
$tables->addPrimaryKey('mymodule_items', 'item_id');
// Composite primary key
$tables->addPrimaryKey('mymodule_item_tags', 'item_id, tag_id');
$tables->executeQueue();
$tables->useTable('mymodule_items');
// Simple index
$tables->addIndex('idx_category', 'mymodule_items', 'category_id');
// Unique index
$tables->addIndex('idx_slug', 'mymodule_items', 'slug', true);
// Composite index
$tables->addIndex('idx_cat_status', 'mymodule_items', 'category_id, status');
$tables->executeQueue();
$tables->useTable('mymodule_items');
$tables->dropIndex('idx_old_index', 'mymodule_items');
$tables->executeQueue();
// Useful for cleaning up auto-generated index names
$tables->dropIndexes('mymodule_items');
$tables->executeQueue();
$tables->dropPrimaryKey('mymodule_items');
$tables->executeQueue();
$tables->useTable('mymodule_categories');
$tables->insert('mymodule_categories', [
'category_id' => 1,
'name' => 'General',
'weight' => 0
]);
// Without automatic quoting (for expressions)
$tables->insert('mymodule_logs', [
'created' => 'NOW()',
'message' => "'Test message'"
], false);
$tables->executeQueue();
$tables->useTable('mymodule_items');
// Update with criteria object
$criteria = new Criteria('status', 0);
$tables->update('mymodule_items', ['status' => 1], $criteria);
// Update with string criteria
$tables->update('mymodule_items', ['hits' => 0], 'hits IS NULL');
$tables->executeQueue();
$tables->useTable('mymodule_items');
// Delete with criteria
$criteria = new Criteria('status', -1);
$tables->delete('mymodule_items', $criteria);
// Delete with string criteria
$tables->delete('mymodule_items', 'created < DATE_SUB(NOW(), INTERVAL 1 YEAR)');
$tables->executeQueue();
$tables->useTable('mymodule_cache');
$tables->truncate('mymodule_cache');
$tables->executeQueue();
// Normal execution (respects HTTP method safety)
$result = $tables->executeQueue();
// Force execution even on GET requests
$result = $tables->executeQueue(true);
if (!$result) {
echo 'Error: ' . $tables->getLastError();
}
// Clear queue without executing
$tables->resetQueue();
// Add custom SQL to the queue
$tables->addToQueue('ALTER TABLE ' . $GLOBALS['xoopsDB']->prefix('mymodule_items') . ' CONVERT TO CHARACTER SET utf8mb4');
$tables->executeQueue();
$tables = new Tables();
if (!$tables->addTable('mymodule_items')) {
$error = $tables->getLastError();
$errno = $tables->getLastErrNo();
// Handle error
}

Kelas Migrate memudahkan penyegerakan perubahan pangkalan data antara versi modul. Ia memanjangkan Tables dengan perbandingan skema dan penyegerakan automatik.

use Xmf\Database\Migrate;
// Create migrate instance for a module
$migrate = new Migrate('mymodule');
// Synchronize database with target schema
$migrate->synchronizeSchema();

Biasanya dipanggil dalam fungsi xoops_module_pre_update_* modul:

function xoops_module_pre_update_mymodule($module, $previousVersion)
{
$migrate = new \Xmf\Database\Migrate('mymodule');
// Perform any pre-sync actions (renames, etc.)
// ...
// Synchronize schema
return $migrate->synchronizeSchema();
}

Untuk pangkalan data besar atau migrasi baris arahan:

$migrate = new Migrate('mymodule');
$statements = $migrate->getSynchronizeDDL();
// Execute statements in batches or from CLI
foreach ($statements as $sql) {
// Process each statement
}

Sesetengah perubahan memerlukan pengendalian yang jelas sebelum penyegerakan. Lanjutkan Migrate untuk migrasi kompleks:

class MyModuleMigrate extends \Xmf\Database\Migrate
{
public function preSyncActions()
{
// Rename a table before sync
$this->useTable('mymodule_old_name');
$this->renameTable('mymodule_old_name', 'mymodule_new_name');
$this->executeQueue();
// Rename a column
$this->useTable('mymodule_items');
$this->alterColumn(
'mymodule_items',
'old_column',
'VARCHAR(255) NOT NULL',
'new_column'
);
$this->executeQueue();
}
}
// Usage
$migrate = new MyModuleMigrate('mymodule');
$migrate->preSyncActions();
$migrate->synchronizeSchema();
$migrate = new Migrate('mymodule');
$currentSchema = $migrate->getCurrentSchema();
$targetSchema = $migrate->getTargetDefinitions();

Untuk pembangun modul menangkap skema selepas perubahan pangkalan data:

$migrate = new Migrate('mymodule');
$migrate->saveCurrentSchema();
// Saves schema to module's sql/migrate.yml

Nota Pembangun: Sentiasa buat perubahan pada pangkalan data dahulu, kemudian jalankan saveCurrentSchema(). Jangan edit fail skema yang dijana secara manual.

Kelas TableLoad memudahkan pemuatan data awal ke dalam jadual. Berguna untuk pembenihan jadual dengan data lalai semasa pemasangan modul.

use Xmf\Database\TableLoad;
$data = [
['category_id' => 1, 'name' => 'General', 'weight' => 0],
['category_id' => 2, 'name' => 'News', 'weight' => 10],
['category_id' => 3, 'name' => 'Events', 'weight' => 20]
];
$count = TableLoad::loadTableFromArray('mymodule_categories', $data);
echo "Inserted {$count} rows";
// Load from YAML file
$count = TableLoad::loadTableFromYamlFile(
'mymodule_categories',
XOOPS_ROOT_PATH . '/modules/mymodule/sql/categories.yml'
);

YAML format:

-
category_id: 1
name: General
weight: 0
-
category_id: 2
name: News
weight: 10
// Count all rows
$total = TableLoad::countRows('mymodule_items');
// Count with criteria
$criteria = new Criteria('status', 1);
$activeCount = TableLoad::countRows('mymodule_items', $criteria);
// Extract all rows
$rows = TableLoad::extractRows('mymodule_items');
// Extract with criteria
$criteria = new Criteria('category_id', 5);
$rows = TableLoad::extractRows('mymodule_items', $criteria);
// Skip certain columns
$rows = TableLoad::extractRows('mymodule_items', null, ['password', 'token']);
// Save all data
TableLoad::saveTableToYamlFile(
'mymodule_categories',
'/path/to/categories.yml'
);
// Save filtered data
$criteria = new Criteria('is_default', 1);
TableLoad::saveTableToYamlFile(
'mymodule_settings',
'/path/to/default_settings.yml',
$criteria
);
// Save without certain columns
TableLoad::saveTableToYamlFile(
'mymodule_items',
'/path/to/items.yml',
null,
['created', 'modified']
);
// Empty a table
$affectedRows = TableLoad::truncateTable('mymodule_cache');
$modversion['sqlfile']['mysql'] = 'sql/mysql.sql';
$modversion['tables'] = [
'mymodule_items',
'mymodule_categories',
'mymodule_settings'
];
<?php
use Xmf\Database\Migrate;
use Xmf\Database\Tables;
use Xmf\Database\TableLoad;
function xoops_module_pre_update_mymodule($module, $previousVersion)
{
// Create custom migrate class
$migrate = new MyModuleMigrate('mymodule');
// Handle version-specific migrations
if ($previousVersion < 120) {
// Version 1.2.0 renamed a table
$migrate->renameOldTable();
}
if ($previousVersion < 130) {
// Version 1.3.0 renamed a column
$migrate->renameOldColumn();
}
// Synchronize schema
return $migrate->synchronizeSchema();
}
function xoops_module_update_mymodule($module, $previousVersion)
{
// Post-update data migrations
if ($previousVersion < 130) {
// Load new default settings
TableLoad::loadTableFromYamlFile(
'mymodule_settings',
XOOPS_ROOT_PATH . '/modules/mymodule/sql/new_settings.yml'
);
}
return true;
}
class MyModuleMigrate extends Migrate
{
public function renameOldTable()
{
if ($this->useTable('mymodule_posts')) {
$this->renameTable('mymodule_posts', 'mymodule_items');
$this->executeQueue();
}
}
public function renameOldColumn()
{
if ($this->useTable('mymodule_items')) {
$this->alterColumn(
'mymodule_items',
'post_title',
"VARCHAR(255) NOT NULL DEFAULT ''",
'title'
);
$this->executeQueue();
}
}
}
KaedahPenerangan
addTable($table)Muatkan atau buat skema jadual
useTable($table)Muatkan jadual sedia ada sahaja
renameTable($table, $newName)Namakan semula jadual baris gilir
setTableOptions($table, $options)Pilihan jadual baris gilir berubah
dropTable($table)Jatuhkan jadual baris gilir
copyTable($table, $newTable, $withData)Salinan jadual giliran
addColumn($table, $column, $attributes)Penambahan lajur baris gilir
alterColumn($table, $column, $attributes, $newName)Perubahan lajur baris gilir
getColumnAttributes($table, $column)Dapatkan definisi lajur
dropColumn($table, $column)Penurunan lajur baris gilir
getTableIndexes($table)Dapatkan definisi indeks
addPrimaryKey($table, $column)Kunci utama baris gilir
addIndex($name, $table, $column, $unique)Indeks baris gilir
dropIndex($name, $table)Penurunan indeks baris gilir
dropIndexes($table)Baris gilir semua indeks jatuh
dropPrimaryKey($table)Gugurkan kunci utama baris gilir
insert($table, $columns, $quote)Sisipan baris gilir
update($table, $columns, $criteria, $quote)Kemas kini baris gilir
delete($table, $criteria)Padam baris gilir
truncate($table)Penggal baris gilir
executeQueue($force)Laksanakan operasi beratur
resetQueue()Kosongkan baris gilir
addToQueue($sql)Tambah mentah SQL
getLastError()Dapatkan mesej ralat terakhir
getLastErrNo()Dapatkan kod ralat terakhir
KaedahPenerangan
__construct($dirname)Cipta untuk modul
synchronizeSchema()Segerakkan pangkalan data untuk menyasarkan
getSynchronizeDDL()Dapatkan DDL penyata
preSyncActions()Gantikan untuk tindakan tersuai
getCurrentSchema()Dapatkan skema pangkalan data semasa
getTargetDefinitions()Dapatkan skema sasaran
saveCurrentSchema()Simpan skema untuk pembangun
KaedahPenerangan
loadTableFromArray($table, $data)Muatkan daripada tatasusunan
loadTableFromYamlFile($table, $file)Muatkan daripada YAML
truncateTable($table)Meja kosong
countRows($table, $criteria)Kira baris
extractRows($table, $criteria, $skip)Ekstrak baris
saveTableToYamlFile($table, $file, $criteria, $skip)Simpan ke YAML
  • ../XMF-Rangka Kerja - Gambaran keseluruhan rangka kerja
  • ../Asas/XMF-Modul-Helper - Kelas pembantu modul
  • Metagen - Utiliti metadata

#XMF #database #migration #schema #tables #ddl