Performance and settings updates: - Add a new jellyfin_library_mappings column to the settings table and wire it into the Settings model (update handling and default value). This enables storing Jellyfin library mappings in settings. - Optimize Cast::list by loading all cast filmography in a single joined query and grouping results per cast to avoid N+1 queries. - Remove per-item cast/staff loading in Media model to avoid repeated queries during list/search operations. - Remove game-specific enrichment from MediaController search to stop extra game info lookups during search responses. These changes reduce repeated DB calls and centralize Jellyfin mapping storage.
PHP Media API
Eine schnelle und zuverlässige PHP-API für die Verwaltung von Medieninhalten mit vollständigen CRUD-Operationen.
Architektur
Die API ist in MVC-ähnliche Struktur aufgeteilt für bessere Wartbarkeit und Erweiterbarkeit:
- index.php (35 Zeilen) - Entry Point und Request-Handling
- Router.php - Routing-Logik
- controllers/ - Controller für HTTP-Requests
- MediaController.php
- CastController.php
- models/ - Datenbank-Modelle
- BaseModel.php - Abstrakte Basisklasse mit CRUD-Methoden
- Media.php - Media Model mit Relationen
- Cast.php - Cast Model mit Filmographie
- AdultCast.php - Erweitertes Cast Model für Adult-Actors
- MediaType.php - Abstrakte Basisklasse für Medientypen
- Movie.php - Movie-spezifische Logik
- Series.php - Series-spezifische Logik
- Music.php - Music-spezifische Logik
- Game.php - Game-spezifische Logik
- Console.php - Console-spezifische Logik
- Adult.php - Adult-spezifische Logik
- database.php - Datenbankverbindung und Tabellen-Erstellung
- config.php - Konfiguration
- services/ - Services für Hilfsfunktionen
- DocumentationService.php - Automatische API-Dokumentation
Installation
- Stelle sicher, dass PHP und SQLite installiert sind
- Die Datenbank wird automatisch beim ersten Aufruf erstellt
- Konfiguriere deinen Webserver (Apache/nginx) so, dass er auf den
api-Ordner zeigt
Automatische API-Dokumentation
Die API verfügt über eine automatische Dokumentation, die sich dynamisch aus den Controllern und Modellen generiert:
GET /api/docs- Vollständige API-Dokumentation als JSON
Die Dokumentation scannt alle Controller und Modelle und extrahiert:
- Alle verfügbaren Endpunkte
- HTTP-Methoden
- Parameter und deren Typen
- Rückgabewerte
- Beschreibungen aus PHPDoc-Kommentaren
Erweiterung der Dokumentation: Füge einfach PHPDoc-Kommentare zu deinen Controller-Methoden hinzu:
/**
* Create a new media item
* @param array $data Media data
* @return array Created media ID
*/
private function create() {
// ...
}
Die Dokumentation wird automatisch beim nächsten Aufruf aktualisiert.
Endpunkte
Media-Endpunkte
GET /api/media- Alle Medien abrufen (mit Filterung und Pagination)GET /api/media/:id- Ein spezifisches Medium abrufenPOST /api/media- Neues Medium erstellenPUT /api/media/:id- Medium aktualisierenDELETE /api/media/:id- Medium löschen
Episoden-Endpunkte (für Series)
GET /api/media/:id/episodes- Alle Episoden einer Serie abrufenGET /api/media/:id/episodes?season=1- Episoden einer bestimmten Staffel abrufenGET /api/media/:id/episodes/:episodeId- Einzelne Episode abrufenPOST /api/media/:id/episodes- Neue Episode zur Serie hinzufügenPUT /api/media/:id/episodes/:episodeId- Episode aktualisierenDELETE /api/media/:id/episodes/:episodeId- Episode löschen
Tracks-Endpunkte (für Music/Alben)
GET /api/media/:id/tracks- Alle Tracks eines Albums abrufenGET /api/media/:id/tracks/:trackId- Einzelnen Track abrufenPOST /api/media/:id/tracks- Neuen Track zum Album hinzufügenPUT /api/media/:id/tracks/:trackId- Track aktualisierenDELETE /api/media/:id/tracks/:trackId- Track löschen
Cast/Staff-Endpunkte
GET /api/cast- Alle Cast-Mitglieder abrufenGET /api/cast/:id- Ein spezifisches Cast-Mitglied abrufen (mit Filmographie)GET /api/cast/:id/media- Alle Medien eines Cast-Mitglieds abrufenPOST /api/cast- Neues Cast-Mitglied erstellen (Stammdaten)PUT /api/cast/:id- Cast-Mitglied aktualisierenDELETE /api/cast/:id- Cast-Mitglied löschen
Adult-Actor Endpunkte (erweiterte Cast-Infos)
GET /api/cast/adult- Alle Adult-Actors mit spezifischen Infos abrufenGET /api/cast/adult?ethnicity=Caucasian&hair_color=Blonde- Adult-Actors filternGET /api/cast/:id/adult- Adult-Actor mit spezifischen Infos abrufenPOST /api/cast/adult- Neuen Adult-Actor mit spezifischen Infos erstellenPUT /api/cast/:id/adult- Adult-Actor und spezifische Infos aktualisierenDELETE /api/cast/:id/adult- Spezifische Adult-Infos löschen
Query-Parameter
Media-Filter
category- Filter nach Kategorie (Movies, Anime, Music, etc.)type- Filter nach Typ (Movie, TV, Album, etc.)search- Suche in Titel und Beschreibungpage- Seitenzahl (Standard: 1)limit- Ergebnisse pro Seite (Standard: 20)
Cast-Filter
search- Suche nach Namepage- Seitenzahllimit- Ergebnisse pro Seite
Beispiele
Neues Medium erstellen
curl -X POST http://localhost/api/media \
-H "Content-Type: application/json" \
-d '{
"title": "Inception",
"year": "2010",
"category": "Movies",
"type": "Movie",
"description": "Ein Dieb...",
"rating": 8.8,
"genres": ["Sci-Fi", "Action"],
"director": "Christopher Nolan",
"staff": [
{
"id": 1,
"role": "Actor",
"characterName": "Cobb"
},
{
"name": "Marion Cotillard",
"role": "Actor",
"characterName": "Mal",
"photo": "https://example.com/photo.jpg"
}
]
}'
Neues Cast-Mitglied erstellen
curl -X POST http://localhost/api/cast \
-H "Content-Type: application/json" \
-d '{
"name": "Leonardo DiCaprio",
"photo": "https://example.com/photo.jpg",
"bio": "Amerikanischer Schauspieler",
"birthDate": "1974-11-11",
"birthPlace": "Los Angeles",
"occupations": ["Actor", "Producer"]
}'
Alle Medien eines Cast-Mitglieds abrufen
curl http://localhost/api/cast/1/media
Serie mit Episoden erstellen
curl -X POST http://localhost/api/media \
-H "Content-Type: application/json" \
-d '{
"title": "Breaking Bad",
"year": "2008",
"category": "Movies",
"type": "TV",
"description": "Ein Chemielehrer...",
"genres": ["Drama", "Crime"],
"episodes": [
{
"season": 1,
"episode_number": 1,
"title": "Pilot",
"description": "Erste Episode",
"air_date": "2008-01-20",
"duration": 58
},
{
"season": 1,
"episode_number": 2,
"title": "Cat's in the Bag...",
"duration": 48
}
]
}'
Episode zu einer Serie hinzufügen
curl -X POST http://localhost/api/media/1/episodes \
-H "Content-Type: application/json" \
-d '{
"season": 2,
"episode_number": 1,
"title": "Seven Thirty-Seven",
"duration": 47
}'
Episoden einer Staffel abrufen
curl "http://localhost/api/media/1/episodes?season=1"
Album mit Tracklist erstellen
curl -X POST http://localhost/api/media \
-H "Content-Type: application/json" \
-d '{
"title": "Dark Side of the Moon",
"year": "1973",
"category": "Music",
"type": "Album",
"artist": "Pink Floyd",
"genres": ["Progressive Rock"],
"tracks": [
{
"track_number": 1,
"title": "Speak to Me",
"duration": 90
},
{
"track_number": 2,
"title": "Breathe",
"duration": 274
}
]
}'
Track zu einem Album hinzufügen
curl -X POST http://localhost/api/media/2/tracks \
-H "Content-Type: application/json" \
-d '{
"track_number": 3,
"title": "On the Run",
"duration": 225
}'
Adult-Actor mit spezifischen Infos erstellen
curl -X POST http://localhost/api/cast/adult \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Doe",
"photo": "https://example.com/photo.jpg",
"bio": "Adult actress",
"birthDate": "1995-05-15",
"birthPlace": "Los Angeles",
"occupations": ["Adult Actress", "Model"],
"adult_specifics": {
"bust_size": "34",
"cup_size": "D",
"waist_size": "24",
"hip_size": "34",
"height": 170,
"weight": 55,
"hair_color": "Blonde",
"eye_color": "Blue",
"ethnicity": "Caucasian",
"tattoos": "None",
"piercings": "Ears",
"measurements": "34D-24-34",
"shoe_size": "38"
}
}'
Adult-Actors nach Ethnie filtern
curl "http://localhost/api/cast/adult?ethnicity=Caucasian&hair_color=Blonde"
Medien abrufen mit Filter
curl "http://localhost/api/media?category=Movies&search=inception"
Medium aktualisieren
curl -X PUT http://localhost/api/media/1 \
-H "Content-Type: application/json" \
-d '{"rating": 9.0}'
Medium löschen
curl -X DELETE http://localhost/api/media/1
Datenstruktur
Media-Objekt
{
"id": 1,
"title": "Titel",
"year": "2024",
"poster": "URL",
"banner": "URL",
"description": "Beschreibung",
"rating": 8.5,
"category": "Movies",
"type": "Movie",
"genres": ["Action", "Drama"],
"tags": ["tag1", "tag2"],
"studios": ["Studio1"],
"runtime": 120,
"director": "Regisseur",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
Cast-Objekt (Stammdaten)
{
"id": 1,
"name": "Name",
"photo": "URL",
"bio": "Biografie",
"birthDate": "1990-01-01",
"birthPlace": "Ort",
"occupations": ["Actor", "Producer"],
"filmography": [
{
"id": 1,
"title": "Film Titel",
"year": "2020",
"role": "Actor",
"characterName": "Charakter"
}
]
}
Cast-Zuordnung in Media
{
"staff": [
{
"id": 1,
"role": "Actor",
"characterName": "Cobb",
"characterImage": "URL"
},
{
"name": "Neuer Schauspieler",
"role": "Actor",
"characterName": "Charakter"
}
]
}
Episode-Objekt
{
"id": 1,
"media_id": 1,
"season": 1,
"episode_number": 1,
"title": "Pilot",
"description": "Beschreibung der Episode",
"air_date": "2008-01-20",
"duration": 58,
"thumbnail": "URL"
}
Track-Objekt
{
"id": 1,
"media_id": 2,
"track_number": 1,
"title": "Speak to Me",
"duration": 90,
"artist": "Pink Floyd"
}
Adult-Specifics Objekt
{
"id": 1,
"cast_id": 1,
"bust_size": "34",
"cup_size": "D",
"waist_size": "24",
"hip_size": "34",
"height": 170,
"weight": 55,
"hair_color": "Blonde",
"eye_color": "Blue",
"ethnicity": "Caucasian",
"tattoos": "None",
"piercings": "Ears",
"measurements": "34D-24-34",
"shoe_size": "38"
}
Features
- ✅ Vollständige CRUD-Operationen
- ✅ SQLite-Datenbank (keine zusätzliche Konfiguration nötig)
- ✅ JSON-basierte API
- ✅ CORS-Unterstützung
- ✅ Filterung und Suche
- ✅ Pagination
- ✅ Automatische Datenbank-Erstellung
- ✅ Relationale Daten (Genres, Tags, Studios, Cast)
- ✅ n:m Beziehung zwischen Cast und Media (Cast-Mitglied nur einmal anlegen, mehreren Medien zuordnen)
- ✅ Automatische Cast-Erkennung anhand Name beim Media-Upload
- ✅ Filmographie für jedes Cast-Mitglied
- ✅ Modularer Aufbau mit MVC-ähnlicher Struktur
- ✅ Typ-spezifische Modelle (Movie, Series, Music, Game, Console, Adult)
- ✅ Erweiterbare Architektur für neue Medientypen
- ✅ Episoden und Staffeln für Serien
- ✅ Tracklisten für Musikalben
- ✅ Typ-spezifische Endpunkte für Episoden und Tracks
- ✅ Adult-Actors mit erweiterten Informationen (Maße, Aussehen, etc.)
- ✅ Filterung von Adult-Actors nach Ethnie, Haarfarbe, etc.
- ✅ Automatische API-Dokumentation via GET /api/docs
- ✅ Dynamische Dokumentation aus PHPDoc-Kommentaren
Erweiterung für neue Medientypen
Um einen neuen Medientyp hinzuzufügen:
- Neue Klasse in
models/erstellen, die vonMediaTypeerbt:
<?php
require_once __DIR__ . '/MediaType.php';
class Book extends MediaType {
protected function getType() {
return 'Book';
}
protected function getTypeSpecificFields() {
return ['author', 'isbn', 'pages'];
}
protected function validateTypeSpecificFields($data) {
// Typ-spezifische Validierung
}
}
- Controller im Router registrieren (optional)
- Datenbank-Tabelle in
database.phphinzufügen falls nötig