Przejdź do treści
TubePress — bezpłatny, samodzielnie hostowany & aktywnie utrzymywany
Dokumentacja dla deweloperów

Modele i baza danych

Warstwa danych TubePress: klasy modeli, pomocnik bazy danych PDO, zapytania przygotowane, schemat bazy danych i wersjonowane migracje SQL — wyjaśnione.

TubePress komunikuje się z MySQL/MariaDB przez dwie cienkie warstwy: modele (jedna klasa statyczna na encję) i helpera Database (mały wrapper nad PDO). Nie ma ORM ani query buildera do nauki — tylko prepared statements i przewidywalne nazwy metod.

Warstwa modeli

Każda główna encja ma model w src/Models/ udostępniający metody statyczne. Dostępne modele to Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig i 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);

Modele hermetyzują złączenia i filtry charakterystyczne dla swojej encji — na przykład Video::find() zwraca film razem z dołączonymi kategoriami, tagami, wykonawcami i kanałami, dzięki czemu kontrolery i szablony pozostają proste.

Helper Database

W przypadkach nieobsłużonych przez model użyj helpera Database bezpośrednio. Każda metoda korzysta z prepared statements — nigdy nie łącz danych wejściowych użytkownika z SQL.

MetodaZwracaCel
Database::fetchOne($sql, $params)array\|nullPierwszy pasujący wiersz.
Database::fetchAll($sql, $params)arrayWszystkie pasujące wiersze.
Database::insert($table, $data)intWstawia tablicę asocjacyjną; zwraca nowe id.
Database::update($table, $data, $where, $whereParams)intAktualizacja; zwraca liczbę zmienionych wierszy.
Database::delete($table, $where, $params)intUsunięcie; zwraca liczbę zmienionych wierszy.
Database::count($table, $where, $params)intLiczba wierszy.
Database::query($sql, $params)PDOStatementDowolne polecenie, pełna kontrola.
Database::transaction($callback)mixedUruchamia domknięcie w transakcji (automatyczny commit/rollback).
$rows = Database::fetchAll(
    "SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
    ['published', 20]
);

$newId = Database::insert('categories', [
    'name' => 'Amateur',
    'slug' => 'amateur',
]);
Odporne połączenia. Helper używa utf8mb4, prawdziwych prepared statements (bez emulacji) i trybu błędów opartego na wyjątkach, a po wykryciu błędu „server has gone away" automatycznie łączy się ponownie — dzięki czemu długo działające workery przeżywają bezczynny timeout MySQL.

Transakcje

Opakuj wieloetapowe zapisy, aby wszystkie się powiodły lub wszystkie zostały wycofane:

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,
        ]);
    }
});

Schemat bazy danych

Baza danych używa przejrzystego, znormalizowanego schematu MySQL. Tabele główne to users, settings, categories, tags, performers, channels, videos oraz tabele złączeń video_categories, video_tags, video_performers — a także comments, user_favorites, user_history, video_likes, pages, plugins, themes i migrations. Opcjonalne podsystemy dodają własne tabele (zadania importu, zasoby mediów, zadania/serwery transkodowania, strefy/miejsca reklamowe, raporty, źródła feedów, tabele tłumaczeń i inne) w miarę ich włączania.

Migracje

Zmiany schematu przechowywane są w sql/ jako pliki numerowane — 001_users.sql, 002_settings.sql, … — aplikowane kolejno przez Migrator::run() podczas instalacji i po każdej aktualizacji. Każda migracja jest addytywna i rejestrowana w tabeli migrations, dzięki czemu nigdy nie jest uruchamiana dwukrotnie.

  • Aby rozszerzyć schemat z poziomu pluginu, dołącz swoje polecenia CREATE TABLE i uruchom je w metodzie install() pluginu (zob. Hooki & pluginy).
  • Nigdy nie zmieniaj numeracji ani nie edytuj zastosowanej migracji — dodaj nową, z wyższym numerem.

Tworzenie modelu

Model to prosta klasa statyczna opakowująca helpera Database dla jednej tabeli:

class Promo
{
    public static function current(): ?array
    {
        return Database::fetchOne(
            "SELECT * FROM promos WHERE active = 1
             ORDER BY id DESC LIMIT 1"
        );
    }
}

Następne kroki

Nadal masz problem?

Otwórz zgłoszenie z poziomu panelu, a nasz zespół Ci pomoże.

Wypróbuj demo na żywo → Pobierz TubePress →