모델 및 데이터베이스
TubePress 데이터 계층: 모델 클래스, PDO 데이터베이스 헬퍼, 준비된 명령문(prepared statement), 데이터베이스 스키마, 버전 관리되는 SQL 마이그레이션을 설명합니다.
TubePress는 두 개의 얇은 레이어를 통해 MySQL/MariaDB와 통신합니다: 모델(엔티티당 하나의 정적 클래스)과 Database 헬퍼(PDO의 간단한 래퍼). ORM도 없고 배울 쿼리 빌더도 없습니다 — 준비된 구문과 예측 가능한 메서드 이름만 있습니다.
모델 레이어
각 핵심 엔티티는 src/Models/에 정적 메서드를 제공하는 모델을 가지고 있습니다. 사용 가능한 모델은 Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig 및 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);모델은 각 엔티티에 특정한 조인과 필터를 캡슐화합니다 — 예를 들어 Video::find()는 카테고리, 태그, 출연자 및 채널이 함께 첨부된 비디오를 반환하므로 컨트롤러와 템플릿이 단순하게 유지됩니다.
Database 헬퍼
모델이 아직 다루지 않는 모든 것에 대해서는 Database 헬퍼를 직접 사용하십시오. 모든 메서드는 준비된 구문을 사용합니다 — 사용자 입력을 SQL에 절대로 직접 연결하지 마십시오.
| 메서드 | 반환값 | 목적 |
|---|---|---|
Database::fetchOne($sql, $params) | array\|null | 첫 번째 일치하는 행. |
Database::fetchAll($sql, $params) | array | 모든 일치하는 행. |
Database::insert($table, $data) | int | 연관 배열을 삽입하고 새 id를 반환합니다. |
Database::update($table, $data, $where, $whereParams) | int | 업데이트하고 영향받은 행 수를 반환합니다. |
Database::delete($table, $where, $params) | int | 삭제하고 영향받은 행 수를 반환합니다. |
Database::count($table, $where, $params) | int | 행 수. |
Database::query($sql, $params) | PDOStatement | 완전한 제어를 위한 임의의 구문. |
Database::transaction($callback) | mixed | 트랜잭션 내에서 클로저를 실행합니다(자동 커밋/롤백). |
$rows = Database::fetchAll(
"SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
['published', 20]
);
$newId = Database::insert('categories', [
'name' => 'Amateur',
'slug' => 'amateur',
]);utf8mb4, 실제 준비된 구문(에뮬레이션 없음) 및 예외 오류 모드를 사용하며, 실제 "server has gone away" 오류 발생 시 한 번 자동으로 재연결합니다 — 따라서 장시간 실행되는 워커가 MySQL 유휴 타임아웃에서도 살아남습니다.트랜잭션
모든 단계가 성공하거나 모두 롤백되도록 다단계 쓰기를 래핑합니다:
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,
]);
}
});스키마
데이터베이스는 정규화된 깔끔한 MySQL 스키마를 사용합니다. 핵심 테이블에는 users, settings, categories, tags, performers, channels, videos와 조인 테이블 video_categories, video_tags, video_performers — 그리고 comments, user_favorites, user_history, video_likes, pages, plugins, themes 및 migrations가 포함됩니다. 선택적 서브시스템은 활성화할 때 자체 테이블(임포트 작업, 미디어 저장소, 트랜스코드 작업/서버, 광고 영역/스팟, 보고서, 피드 소스, 번역 테이블 등)을 추가합니다.
마이그레이션
스키마 변경 사항은 sql/에 번호가 매겨진 파일 — 001_users.sql, 002_settings.sql, … — 로 저장되며, 설치 및 업데이트 후 Migrator::run()에 의해 순서대로 적용됩니다. 각 마이그레이션은 추가적이며 migrations 테이블에 기록되어 두 번 실행되지 않습니다.
- 플러그인에서 스키마를 확장하려면
CREATE TABLE구문을 작성하고 플러그인의install()메서드에서 실행하십시오(훅 & 플러그인 참조). - 적용된 마이그레이션의 번호를 변경하거나 편집하지 마십시오 — 더 높은 번호의 새 마이그레이션을 추가하십시오.
모델 작성
모델은 하나의 테이블을 위해 Database 헬퍼를 래핑하는 단순한 정적 클래스입니다:
class Promo
{
public static function current(): ?array
{
return Database::fetchOne(
"SELECT * FROM promos WHERE active = 1
ORDER BY id DESC LIMIT 1"
);
}
}