e38a6e1f7b39a08efe250143f5d8ed5a18135578
Apply strict_types and extensive type declarations throughout the API and models, improving type safety and error handling. Key changes: add declare(strict_types=1) to many files; convert properties, method parameters and return values to typed signatures (PDO, arrays, ints, strings, bools, nullables); switch exception handling to Throwable in index and Router; improve Router, controllers and model method signatures and nullability handling; refine file/image serving security checks and headers in ImageController; strengthen Database typing and initialization methods; return explicit types from BaseModel CRUD helpers and counting; update Media/Cast/Adult/Game/Console/Settings controllers and models to use typed methods, better validation, and clearer update/create return types. Also add AGENTS.md (agent skills index), update README with Swagger/OpenAPI usage instructions, and add /.windsurf to .gitignore. These changes aim to harden runtime correctness, make intended contracts explicit, and prepare the codebase for easier maintenance and static analysis.
Kyoo Backend
A RESTful API backend for media management, supporting movies, TV series, music albums, games, and cast information.
Features
- Media Management: CRUD operations for movies, TV series, music albums, and games
- Cast Management: Manage actors, directors, and other staff with filmography tracking
- Image Handling: Automatic processing and storage of posters, banners, and cast photos
- Search & Filtering: Advanced search with pagination support
- API Logging: Built-in request/response logging for debugging
- Docker Support: Easy deployment with Docker Compose
- Auto Documentation: Self-documenting API endpoint
Tech Stack
- PHP 8.2 with Apache
- MariaDB 10.11
- Docker & Docker Compose
- phpMyAdmin for database management
Quick Start
Prerequisites
- Docker installed
- Docker Compose installed
Installation
- Clone the repository:
git clone <repository-url>
cd kyoobackend
- Start the services:
docker-compose up -d --build
- Access the API:
- API Base URL:
http://localhost:6400/api - phpMyAdmin:
http://localhost:6402
Database Credentials
- Host:
mariadb(within Docker) orlocalhost:6401(from host) - Database:
kyoo - User:
kyoo_user - Password:
kyoo_password - Root Password:
root_password
Project Structure
kyoobackend/
├── api/
│ ├── controllers/ # Request handlers
│ │ ├── MediaController.php
│ │ ├── CastController.php
│ │ ├── ImageController.php
│ │ └── SettingsController.php
│ ├── models/ # Data models
│ │ ├── Media.php
│ │ ├── Cast.php
│ │ ├── Game.php
│ │ ├── Series.php
│ │ ├── Music.php
│ │ └── ...
│ ├── services/ # Business logic
│ │ ├── ApiLogger.php
│ │ ├── ImageHandler.php
│ │ └── DocumentationService.php
│ ├── config.php # Configuration
│ ├── database.php # Database connection
│ ├── Router.php # API routing
│ └── index.php # Entry point
├── docker-compose.yml # Docker configuration
├── Dockerfile # PHP container build
└── php-custom.ini # PHP configuration
API Endpoints
Root
GET /api- API information and available endpoints
Documentation
GET /api/docs- Auto-generated API documentation
Media
GET /api/media- Get all media (with pagination and filtering)GET /api/media/:id- Get specific media itemPOST /api/media- Create new mediaPUT /api/media/:id- Update mediaDELETE /api/media/:id- Delete media
Series Episodes
GET /api/media/:id/episodes- Get all episodes for a seriesGET /api/media/:id/episodes/:episodeId- Get specific episodePOST /api/media/:id/episodes- Add episode to seriesPUT /api/media/:id/episodes/:episodeId- Update episodeDELETE /api/media/:id/episodes/:episodeId- Delete episode
Music Tracks
GET /api/media/:id/tracks- Get all tracks for an albumGET /api/media/:id/tracks/:trackId- Get specific trackPOST /api/media/:id/tracks- Add track to albumPUT /api/media/:id/tracks/:trackId- Update trackDELETE /api/media/:id/tracks/:trackId- Delete track
Cast
GET /api/cast- Get all cast members (with search)GET /api/cast/:id- Get specific cast member with filmographyGET /api/cast/:id/media- Get all media for a cast memberPOST /api/cast- Create new cast memberPUT /api/cast/:id- Update cast memberDELETE /api/cast/:id- Delete cast member
Adult Cast
GET /api/cast/adult- Get all adult cast members (with filters)GET /api/cast/adult/:id- Get specific adult cast memberPOST /api/cast/adult- Create new adult cast memberPUT /api/cast/adult/:id- Update adult cast memberDELETE /api/cast/adult/:id- Delete adult cast member
Images
GET /api/images/*- Serve images directly
Settings
GET /api/settings- Get application settingsPUT /api/settings- Update settings
Query Parameters
Media List
page- Page number (default: 1)limit- Items per page (default: 20)category- Filter by category (e.g., "movie", "tv", "music", "game")type- Filter by type (e.g., "Movie", "TV", "Album", "Game")search- Search in title and description
Cast List
page- Page number (default: 1)limit- Items per page (default: 20)search- Search by name
Adult Cast List
page- Page number (default: 1)limit- Items per page (default: 20)search- Search by nameethnicity- Filter by ethnicityhair_color- Filter by hair color
Series Episodes
season- Filter by season number
Data Models
Media
{
"id": 1,
"title": "Movie Title",
"cleanname": "movie-title",
"year": 2024,
"poster": "/images/movies/poster_xxx.webp",
"banner": "/images/movies/banner_xxx.webp",
"description": "Description text",
"rating": 8.5,
"category": "movie",
"type": "Movie",
"status": "released",
"aspectRatio": "16:9",
"runtime": 120,
"director": "Director Name",
"writer": "Writer Name",
"source": "netflix",
"releaseDate": "2024-01-01",
"genres": ["Action", "Drama"],
"tags": ["tag1", "tag2"],
"studios": ["Studio1"],
"staff": [
{
"id": 1,
"name": "Actor Name",
"role": "Actor",
"characterName": "Character",
"characterImage": "/images/characters/char_xxx.webp"
}
],
"createdAt": "2024-01-01 00:00:00",
"updatedAt": "2024-01-01 00:00:00"
}
Cast
{
"id": 1,
"name": "Actor Name",
"cleanname": "actor-name",
"photo": "/images/cast/photo_xxx.webp",
"bio": "Biography text",
"birthDate": "1990-01-01",
"birthPlace": "City, Country",
"occupations": ["Actor", "Director"],
"filmography": [
{
"id": 1,
"title": "Movie Title",
"year": 2024,
"poster": "/images/movies/poster_xxx.webp",
"category": "movie",
"type": "Movie",
"role": "Actor",
"characterName": "Character"
}
],
"createdAt": "2024-01-01 00:00:00",
"updatedAt": "2024-01-01 00:00:00"
}
Response Format
All responses follow this structure:
Success
{
"success": true,
"data": { ... }
}
Error
{
"success": false,
"error": "Error message"
}
Paginated List
{
"success": true,
"data": {
"items": [ ... ],
"total": 100,
"page": 1,
"limit": 20,
"totalPages": 5
}
}
Configuration
Environment variables can be set in docker-compose.yml or as system environment variables:
DB_HOST- Database host (default:mariadb)DB_NAME- Database name (default:kyoo)DB_USER- Database user (default:kyoo_user)DB_PASS- Database password (default:kyoo_password)API_LOGGING_ENABLED- Enable API logging (default:false)
Docker Commands
Start services
docker-compose up -d --build
Stop services
docker-compose down
View logs
# All logs
docker-compose logs
# Specific service
docker-compose logs php
docker-compose logs mariadb
Reset database
docker-compose down -v
docker-compose up -d --build
Development
The API files are mounted as volumes, so changes are immediately reflected without rebuilding.
API Logging
Logs are written to:
- API requests/responses:
/var/www/html/logs/api.log - PHP errors:
/var/www/html/logs/php_error.log
Enable logging by setting API_LOGGING_ENABLED=true.
Troubleshooting
PHP container won't start
docker-compose logs php
Database connection errors
Check if MariaDB is running:
docker-compose ps
Tables not created
Tables are auto-created on first API call. Check logs:
docker-compose logs php
Swagger/OpenAPI Documentation
A Swagger/OpenAPI specification file is included at swagger.json in the project root. This file can be used with Swagger UI to interactively test the API.
Using Swagger UI
Option 1: Online Swagger Editor
- Go to https://editor.swagger.io
- Import the
swagger.jsonfile - Click "Try it out" to test endpoints
Option 2: Docker with Swagger UI
docker run -p 8080:8080 -e SWAGGER_JSON=/swagger/swagger.json -v $(pwd):/swagger swaggerapi/swagger-ui
Then access at: http://localhost:8080
Option 3: Local Swagger UI
- Download Swagger UI from https://github.com/swagger-api/swagger-ui
- Extract and open
dist/index.html - Modify the URL to point to your
swagger.jsonfile
API Endpoints Covered
- Root endpoints (API info, auto-docs)
- Media CRUD operations
- Series episodes CRUD operations
- Music tracks CRUD operations
- Cast CRUD operations
- Adult cast CRUD operations
- Settings operations
License
[Add your license here]
Description
Languages
PHP
99.8%
Dockerfile
0.2%