Add PHP Media API scaffold and Docker configs

Initial project scaffold for a PHP Media API including routing, controllers, models and services under api/ (Router, Media/Cast/Image/Settings controllers, models, database/bootstrap files and automatic docs service). Adds Docker support (Dockerfile, docker-compose.yml, DOCKER_README.md, php-custom.ini), .htaccess for pretty URLs, API documentation and example payloads (API_EXAMPLES.md, api/README.md, api_examples/*.json), image handling service and logging, plus a comprehensive .gitignore. This commit provides a runnable development environment and example requests to get the API up and tested quickly.
This commit is contained in:
Lars Behrends
2026-04-12 00:46:30 +02:00
commit 66f69bc90d
54 changed files with 6035 additions and 0 deletions

472
api/README.md Normal file
View File

@@ -0,0 +1,472 @@
# 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
1. Stelle sicher, dass PHP und SQLite installiert sind
2. Die Datenbank wird automatisch beim ersten Aufruf erstellt
3. 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:
```php
/**
* 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 abrufen
- `POST /api/media` - Neues Medium erstellen
- `PUT /api/media/:id` - Medium aktualisieren
- `DELETE /api/media/:id` - Medium löschen
### Episoden-Endpunkte (für Series)
- `GET /api/media/:id/episodes` - Alle Episoden einer Serie abrufen
- `GET /api/media/:id/episodes?season=1` - Episoden einer bestimmten Staffel abrufen
- `GET /api/media/:id/episodes/:episodeId` - Einzelne Episode abrufen
- `POST /api/media/:id/episodes` - Neue Episode zur Serie hinzufügen
- `PUT /api/media/:id/episodes/:episodeId` - Episode aktualisieren
- `DELETE /api/media/:id/episodes/:episodeId` - Episode löschen
### Tracks-Endpunkte (für Music/Alben)
- `GET /api/media/:id/tracks` - Alle Tracks eines Albums abrufen
- `GET /api/media/:id/tracks/:trackId` - Einzelnen Track abrufen
- `POST /api/media/:id/tracks` - Neuen Track zum Album hinzufügen
- `PUT /api/media/:id/tracks/:trackId` - Track aktualisieren
- `DELETE /api/media/:id/tracks/:trackId` - Track löschen
### Cast/Staff-Endpunkte
- `GET /api/cast` - Alle Cast-Mitglieder abrufen
- `GET /api/cast/:id` - Ein spezifisches Cast-Mitglied abrufen (mit Filmographie)
- `GET /api/cast/:id/media` - Alle Medien eines Cast-Mitglieds abrufen
- `POST /api/cast` - Neues Cast-Mitglied erstellen (Stammdaten)
- `PUT /api/cast/:id` - Cast-Mitglied aktualisieren
- `DELETE /api/cast/:id` - Cast-Mitglied löschen
### Adult-Actor Endpunkte (erweiterte Cast-Infos)
- `GET /api/cast/adult` - Alle Adult-Actors mit spezifischen Infos abrufen
- `GET /api/cast/adult?ethnicity=Caucasian&hair_color=Blonde` - Adult-Actors filtern
- `GET /api/cast/:id/adult` - Adult-Actor mit spezifischen Infos abrufen
- `POST /api/cast/adult` - Neuen Adult-Actor mit spezifischen Infos erstellen
- `PUT /api/cast/:id/adult` - Adult-Actor und spezifische Infos aktualisieren
- `DELETE /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 Beschreibung
- `page` - Seitenzahl (Standard: 1)
- `limit` - Ergebnisse pro Seite (Standard: 20)
### Cast-Filter
- `search` - Suche nach Name
- `page` - Seitenzahl
- `limit` - Ergebnisse pro Seite
## Beispiele
### Neues Medium erstellen
```bash
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
```bash
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
```bash
curl http://localhost/api/cast/1/media
```
### Serie mit Episoden erstellen
```bash
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
```bash
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
```bash
curl "http://localhost/api/media/1/episodes?season=1"
```
### Album mit Tracklist erstellen
```bash
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
```bash
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
```bash
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
```bash
curl "http://localhost/api/cast/adult?ethnicity=Caucasian&hair_color=Blonde"
```
### Medien abrufen mit Filter
```bash
curl "http://localhost/api/media?category=Movies&search=inception"
```
### Medium aktualisieren
```bash
curl -X PUT http://localhost/api/media/1 \
-H "Content-Type: application/json" \
-d '{"rating": 9.0}'
```
### Medium löschen
```bash
curl -X DELETE http://localhost/api/media/1
```
## Datenstruktur
### Media-Objekt
```json
{
"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)
```json
{
"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
```json
{
"staff": [
{
"id": 1,
"role": "Actor",
"characterName": "Cobb",
"characterImage": "URL"
},
{
"name": "Neuer Schauspieler",
"role": "Actor",
"characterName": "Charakter"
}
]
}
```
### Episode-Objekt
```json
{
"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
```json
{
"id": 1,
"media_id": 2,
"track_number": 1,
"title": "Speak to Me",
"duration": 90,
"artist": "Pink Floyd"
}
```
### Adult-Specifics Objekt
```json
{
"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:
1. Neue Klasse in `models/` erstellen, die von `MediaType` erbt:
```php
<?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
}
}
```
2. Controller im Router registrieren (optional)
3. Datenbank-Tabelle in `database.php` hinzufügen falls nötig