Veranstaltungen-APP/docs/SETUP.md

11 KiB

🎉 Laravel Event-Portal - Vollständige Implementierung

Dieses Projekt ist ein vollständig arbeitsfertiges Event-Portal für Dresden mit Integration von externen Veranstaltungsquellen.


📋 Projektstruktur

Veranstaltungen-APP/
├── app/
│   ├── Models/
│   │   ├── Source.php              # Quelle (z.B. Stadt Dresden)
│   │   ├── Event.php               # Veranstaltung
│   │   └── EventOccurrence.php      # Einzelne Termine
│   ├── Http/Controllers/
│   │   └── EventController.php      # REST API Controller
│   ├── Jobs/
│   │   └── ImportEventsJob.php      # Queue Job für Import
│   ├── Commands/
│   │   └── ImportEventsCommand.php  # Artisan Command für manuellen Import
│   ├── Services/
│   │   └── EventImportService.php   # Business Logic Service
│
├── database/
│   └── migrations/
│       ├── 2026_04_09_000001_create_sources_table.php
│       ├── 2026_04_09_000002_create_events_table.php
│       └── 2026_04_09_000003_create_event_occurrences_table.php
│
├── routes/
│   └── api.php                      # REST API Routen
│
├── docs/
│   ├── SETUP.md                     # Diese Datei
│   ├── EXAMPLE_QUERIES.php          # Eloquent Query-Beispiele
│   ├── API_RESPONSES.md             # API Response-Formate
│   ├── IMPORT_SCRAPER_INTEGRATION.md # Import-Dokumentation
│   └── KERNEL_SCHEDULER_EXAMPLE.php # Scheduler-Konfiguration

⚙️ Installation & Setup

1. Frisches Laravel-Projekt erstellen

# Laravel 11 LTS (oder aktuelle LTS)
composer create-project laravel/laravel Veranstaltungen-APP

cd Veranstaltungen-APP

2. Diese Dateien in das Projekt kopieren

# Kopiere alle PHP/Migration-Dateien aus diesem Package
# in die entsprechenden Verzeichnisse

# Beispiel:
cp app/Models/*.php ./app/Models/
cp app/Http/Controllers/*.php ./app/Http/Controllers/
cp app/Jobs/*.php ./app/Jobs/
cp app/Commands/*.php ./app/Commands/
cp app/Services/*.php ./app/Services/
cp database/migrations/*.php ./database/migrations/
cp routes/api.php ./routes/

3. Umgebungsvariablen konfigurieren

# .env erstellen
cp .env.example .env

# Schüssel generieren
php artisan key:generate

Bearbeite .env:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=veranstaltungen_app
DB_USERNAME=root
DB_PASSWORD=

QUEUE_CONNECTION=database
MAIL_FROM_ADDRESS=noreply@veranstaltungen-app.de

4. Datenbank & Migrations

# Datenbank erstellen (MariaDB)
mysql -u root -p -e "CREATE DATABASE veranstaltungen_app CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# Migrations ausführen
php artisan migrate

# Optionale Fixtures/Seeds laden
php artisan db:seed --class=SourceSeeder

5. Queue für Imports vorbereiten

# Queue-Tabelle erstellen
php artisan queue:table
php artisan migrate

# Queue Worker starten (Development)
php artisan queue:work --verbose

🚀 Erste Schritte

Event-Quellen erstellen

# Interaktiv via Artisan Tinker
php artisan tinker

>>> $source = \App\Models\Source::create([
...     'name' => 'Stadt Dresden',
...     'description' => 'Offizielle Veranstaltungen der Stadt',
...     'url' => 'https://stadt-dresden.de',
...     'status' => 'active',
... ]);

Events importieren

# Manueller Import (blockierend)
php artisan events:import --sync

# Oder asynchron in Queue
php artisan events:import

# Queue Worker muss laufen für Verarbeitung:
php artisan queue:work

API testen

# Events auflisten
curl "http://localhost:8000/api/events?from=2026-04-15&to=2026-05-31&limit=10"

# Ein Event anzeigen
curl "http://localhost:8000/api/events/1"

# Verfügbare Kategorien
curl "http://localhost:8000/api/events/categories/list"

# Verfügbare Orte
curl "http://localhost:8000/api/events/locations/list"

📚 Dokumentation

Für Event-Queries siehe:

👉 EXAMPLE_QUERIES.php

Für API-Endpoints siehe:

👉 API_RESPONSES.md

Für Import/Scraper-Integration siehe:

👉 IMPORT_SCRAPER_INTEGRATION.md

Für Scheduler-Setup siehe:

👉 KERNEL_SCHEDULER_EXAMPLE.php


🔑 API-Endpoints

Methode Endpoint Beschreibung
GET /api/events Events mit Filtern auflisten
GET /api/events/{id} Einzelnes Event anzeigen
GET /api/events/categories/list Verfügbare Kategorien
GET /api/events/locations/list Verfügbare Orte

Filter-Parameter

GET /api/events
  ?from=2026-04-15          # Ab Datum (YYYY-MM-DD), Standard: heute
  &to=2026-05-31            # Bis Datum (YYYY-MM-DD), Standard: +3 Monate
  &category=Kultur          # Nach Kategorie filtern
  &location=Dresden         # Nach Ort filtern
  &limit=20                 # Ergebnisse pro Seite (1-100, Standard: 20)

🎯 Datenmodell

Events (Veranstaltungen)

  • id - Eindeutige ID
  • source_id - Referenz zur Quelle
  • external_id - ID der Quelle
  • title - Name der Veranstaltung
  • description - Beschreibung
  • location - Ort/Stadt
  • category - Kategorie (z.B. Kultur, Sport)
  • slug - URL-freundlicher Name
  • image_url, website_url, contact_email, contact_phone
  • status - draft | published | archived
  • created_at, updated_at

Event Occurrences (Termine)

  • id - Eindeutige ID
  • event_id - Referenz zum Event
  • start_datetime - Startzeit
  • end_datetime - Endzeit
  • is_all_day - Ganztägig?
  • location_details - Raum/Gebäude
  • capacity - Kapazität
  • available_tickets - Verfügbare Tickets
  • price - Preis (optional)
  • status - scheduled | cancelled | completed

Sources (Quellen)

  • id - Eindeutige ID
  • name - Name der Quelle
  • description - Beschreibung
  • url - Website URL
  • status - active | inactive
  • last_import_at - Letzter Import-Zeitpunkt

🔄 Import-Workflow

1. External Source (z.B. Stadt Dresden API)
   ↓
2. ImportEventsCommand / EventImportService
   ↓
3. ImportEventsJob (läuft in Queue)
   ↓
4. fetchExternalEvents() - Ruft externe Daten ab
   ↓
5. upsertEvent() - Erstellt oder aktualisiert Event+Occurrences
   ↓
6. Database (MySQL/MariaDB)
   ↓
7. API (für Frontend verfügbar)

Upsert-Logik

  • Events werden anhand [source_id, external_id] abgeglichen
  • Existierende Events = Update
  • Neue Events = Insert
  • Verhindert Duplikate durch Unique Index

Geplante Imports (Scheduler)

In app/Console/Kernel.php (siehe Beispiel):

  • 03:00 Uhr - Täglich alle Quellen importieren
  • Stündlich - Stadt-Dresden-Quelle (häufige Updates)
  • Alle 6 Stunden - Andere Quellen
  • 04:00 Uhr - Markiere abgelaufene Termine
  • Sonntag 05:00 - Räume archivierte Events auf

🛠️ Commands

# Event-Import
php artisan events:import [--source=ID|Name] [--sync]

# Queue einrichten
php artisan queue:table
php artisan migrate

# Queue Worker starten (Development)
php artisan queue:work [--verbose] [--tries=3] [--timeout=120]

# Failed Jobs anzeigen
php artisan queue:failed
php artisan queue:retry ID
php artisan queue:forget ID

# Alle Jobs leeren
php artisan queue:flush

# Cache leeren
php artisan cache:clear

# Logs leeren
php artisan log:prune

# Datenbank frisch seeden
php artisan migrate:refresh --seed

📊 Datenbank-Indizes

Die Migrationen erstellen folgende Indizes für Performance:

sources:

  • status (Filter nach aktiv/inaktiv)
  • created_at (Sortierer)

events:

  • source_id (Foreign Key)
  • slug (Unique, für SEO-URLs)
  • [location, status] (Composite Index für Location-Filter)
  • [category, status] (Composite Index für Kategorie-Filter)
  • created_at (Neueste zuerst)
  • [source_id, external_id] (Unique, verhindert Duplikate)

event_occurrences:

  • event_id (Foreign Key)
  • start_datetime (Filter nach Datum)
  • [start_datetime, status] (Composite Index für "nächste Events")
  • [event_id, status] (Filter nach Event & Status)

🔐 Security-Best-Practices

Implementiert:

  • SQL-Injections vermieden (Eloquent ORM)
  • CSRF-Schutz (Laravel Standard)
  • Rate Limiting für APIs
  • Input Validation in Controllers
  • Soft Deletes für Datenintegrität

⚠️ Zu implementieren:

  • API-Authentifizierung (Laravel Passport/Sanctum)
  • Request Throttling
  • CORS-Konfiguration
  • Content Security Policy

🐛 Troubleshooting

Migrations schlagen fehl

# Checke MariaDB Version
mysql --version

# Migrations zurückrollen
php artisan migrate:reset

# Neu starten
php artisan migrate

Queue-Jobs werden nicht verarbeitet

# Worker-Prozess läuft?
ps aux | grep "queue:work"

# Queue starten (Development)
php artisan queue:work --verbose

API gibt 404 zurück

# Checke Routes
php artisan route:list

# Starte Server
php artisan serve

Zu viel Memory-Verbrauch

# Optimize Autoloader
composer install --optimize-autoloader --no-dev

# Disable Query Logging in Production
# In .env: APP_DEBUG=false

📈 Production Deployment

Vorbereitung

# .env für Production
APP_ENV=production
APP_DEBUG=false
QUEUE_CONNECTION=redis  # oder beanstalkd
LOG_CHANNEL=stack

Cron-Job einrichten (Scheduler)

# /etc/cron.d/laravel-scheduler
* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1

Oder mit systemd:

# supervisor für Queue Workers
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/app/artisan queue:work redis --sleep=3 --tries=3 --timeout=90
autostart=true
autorestart=true
numprocs=4
redirect_stderr=true
stdout_logfile=/path/to/app/storage/logs/worker.log

🤝 Weitere Integration

Beispiel: Import aus Stadt-Dresden-API

Bearbeite app/Jobs/ImportEventsJob.php:

protected function fetchExternalEvents()
{
    $response = Http::withHeaders([
        'Accept' => 'application/json',
    ])->get('https://api.stadt-dresden.de/events', [
        'limit' => 1000,
    ]);

    return $response->json('data');
}

Beispiel: Web-Scraping

composer require symfony/dom-crawler symfony/http-client

Dann in Import-Service:

use Symfony\Component\DomCrawler\Crawler;

$response = Http::get('https://example.com/events');
$crawler = new Crawler($response->body());
// ... scrape & extract events

📞 Support & Weitere Ressourcen


Version: 1.0
Laravel: 11 LTS
PHP: 8.2+
Database: MariaDB 10.4+
Erstellt: 9. April 2026