Model & basis data
Lapisan data TubePress: kelas model, helper Database PDO, prepared statement, skema basis data dan migrasi SQL berversi dijelaskan.
TubePress berkomunikasi dengan MySQL/MariaDB melalui dua lapisan tipis: model (satu kelas statis per entitas) dan helper Database (pembungkus kecil di atas PDO). Tidak ada ORM dan tidak ada query builder yang perlu dipelajari — hanya prepared statement dan nama metode yang mudah diprediksi.
Lapisan model
Setiap entitas inti memiliki model di src/Models/ yang mengekspos metode statis. Model yang tersedia adalah Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig dan FooterConfig.
$video = Video::find($id); // one row (or null)
$latest = Video::all(['status' => 'published', 'limit' => 20]);
$id = Video::create($data); // returns new id
Video::update($id, ['title' => 'New title']);
Video::delete($id);Model merangkum join dan filter yang spesifik untuk entitasnya — misalnya Video::find() mengembalikan video beserta kategori, tag, performer, dan channel yang terlampir, sehingga controller dan template tetap sederhana.
Helper Database
Untuk hal apa pun yang belum dicakup model, gunakan helper Database secara langsung. Setiap metode menggunakan prepared statement — jangan pernah menggabungkan input pengguna ke dalam SQL.
| Metode | Mengembalikan | Tujuan |
|---|---|---|
Database::fetchOne($sql, $params) | array\|null | Baris pertama yang cocok. |
Database::fetchAll($sql, $params) | array | Semua baris yang cocok. |
Database::insert($table, $data) | int | Sisipkan array asosiatif; mengembalikan id baru. |
Database::update($table, $data, $where, $whereParams) | int | Perbarui; mengembalikan baris yang terpengaruh. |
Database::delete($table, $where, $params) | int | Hapus; mengembalikan baris yang terpengaruh. |
Database::count($table, $where, $params) | int | Jumlah baris. |
Database::query($sql, $params) | PDOStatement | Pernyataan apa pun, untuk kontrol penuh. |
Database::transaction($callback) | mixed | Jalankan closure dalam transaksi (commit/rollback otomatis). |
$rows = Database::fetchAll(
"SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
['published', 20]
);
$newId = Database::insert('categories', [
'name' => 'Amateur',
'slug' => 'amateur',
]);utf8mb4, prepared statement nyata (tanpa emulasi) dan mode error exception, serta secara otomatis menghubungkan kembali sekali pada error "server has gone away" yang sesungguhnya — sehingga worker yang berjalan lama tetap bertahan saat MySQL timeout idle.Transaksi
Bungkus penulisan multi-langkah agar semuanya berhasil atau semuanya di-rollback:
Database::transaction(function () use ($videoId, $catIds) {
Database::delete('video_categories', 'video_id = ?', [$videoId]);
foreach ($catIds as $cid) {
Database::insert('video_categories', [
'video_id' => $videoId, 'category_id' => $cid,
]);
}
});Skema
Database menggunakan skema MySQL yang bersih dan ternormalisasi. Tabel inti mencakup users, settings, categories, tags, performers, channels, videos dan tabel join video_categories, video_tags, video_performers — ditambah comments, user_favorites, user_history, video_likes, pages, plugins, themes dan migrations. Subsistem opsional menambahkan tabel mereka sendiri (pekerjaan impor, penyimpanan media, pekerjaan/server transcode, zona/spot iklan, laporan, sumber feed, tabel terjemahan dan lainnya) saat Anda mengaktifkannya.
Migrasi
Perubahan skema disimpan di sql/ sebagai file bernomor — 001_users.sql, 002_settings.sql, … — diterapkan secara berurutan oleh Migrator::run() selama instalasi dan setelah setiap pembaruan. Setiap migrasi bersifat aditif dan dicatat dalam tabel migrations sehingga tidak pernah berjalan dua kali.
- Untuk memperluas skema dari plugin, sertakan pernyataan
CREATE TABLEAnda dan jalankan dalam metodeinstall()plugin (lihat Hooks & plugins). - Jangan pernah menomori ulang atau mengedit migrasi yang sudah diterapkan — tambahkan yang baru dengan nomor lebih tinggi.
Menulis model
Model hanyalah kelas statis yang membungkus helper Database untuk satu tabel:
class Promo
{
public static function current(): ?array
{
return Database::fetchOne(
"SELECT * FROM promos WHERE active = 1
ORDER BY id DESC LIMIT 1"
);
}
}Langkah selanjutnya
Masih kesulitan?
Buka tiket dari dasbor Anda dan tim kami akan membantu Anda.