Menu
Coddy logo textTech

Fahrzeugvermietung

Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy. Lektion 91 von 91.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Fahrzeugvermietungssystem, das eine Fahrzeugflotte verwaltet, Kundenmietvorgänge verfolgt und Preise basierend auf dem Fahrzeugtyp berechnet. Diese umfassende Herausforderung bringt Vererbung, Schnittstellen, Kapselung und das Zustandsmuster zusammen, um eine realistische Anwendung für ein Vermietungsgeschäft zu erstellen.

Du organisierst deinen Code über sieben Dateien:

  • VehicleState.php: Definiere eine VehicleState-Schnittstelle, die die verschiedenen Zustände repräsentiert, in denen sich ein Fahrzeug befinden kann. Füge zwei Methoden hinzu: getStatus(): string und canRent(): bool. Erstelle anschließend drei Klassen, die diese Schnittstelle implementieren:
    • AvailableState: gibt "Available" und true zurück
    • RentedState: gibt "Rented" und false zurück
    • MaintenanceState: gibt "Maintenance" und false zurück
  • Vehicle.php: Binde die Datei Vehicle ein. Erstelle eine abstrakte Klasse Vehicle mit Konstruktor-Promotion für licensePlate (string, public readonly), brand (string, public readonly) und dailyRate (float, protected). Speichere den aktuellen Zustand in einer privaten Eigenschaft, die standardmäßig auf AvailableState gesetzt wird. Implementiere:
    • getState(): VehicleState: gibt den aktuellen Zustand zurück
    • setState(VehicleState $state): void: ändert den Zustand
    • getStatus(): string: delegiert an getStatus() des Zustands
    • canRent(): bool: delegiert an canRent() des Zustands
    • abstract calculateCost(int $days): float: jeder Fahrzeugtyp berechnet die Kosten unterschiedlich
    • getType(): string: gibt den Klassennamen mithilfe von static::class zurück
  • Vehicles.php: Binde die Datei Vehicle ein. Erstelle drei konkrete Fahrzeugklassen:
    • Car: erweitert Vehicle; calculateCost() gibt dailyRate * days zurück
    • Motorcycle: erweitert Vehicle; calculateCost() gibt dailyRate * days * 0.8 zurück (20 % Rabatt)
    • Van: erweitert Vehicle mit einem zusätzlichen Parameter $mileageRate (float); calculateCost(int $days, int $miles = 0) gibt (dailyRate * days) + (mileageRate * miles) zurück
  • Customer.php: Erstelle eine Klasse Customer mit Konstruktor-Promotion für id (int, public readonly) und name (string, public readonly). Verfolge die Miethistorie in einem privaten Array. Implementiere:
    • addRental(string $vehiclePlate, float $cost): void: fügt einen Eintrag zur Historie hinzu
    • getRentalCount(): int: gibt die Anzahl der Mietvorgänge zurück
    • getTotalSpent(): float: gibt die Summe aller Mietkosten zurück
  • Rental.php: Binde die Dateien Vehicle und Customer ein. Erstelle eine Klasse Rental, die einen Kunden mit einem Fahrzeug verknüpft. Verwende Konstruktor-Promotion für customer (Customer, public readonly), vehicle (Vehicle, public readonly), days (int, private) und optional miles (int, private, default 0). Implementiere:
    • calculateTotal(): float: Wenn das Fahrzeug ein Van ist, übergib miles an calculateCost(); andernfalls übergib nur days
    • complete(): string: berechnet die Gesamtsumme, fügt sie der Historie des Kunden hinzu, setzt das Fahrzeug auf AvailableState und gibt "Rental completed: $[total]" zurück (2 Dezimalstellen)
  • RentalService.php: Binde die Dateien Rental und Vehicles ein. Erstelle eine Klasse RentalService, die die Fahrzeugflotte verwaltet. Speichere Fahrzeuge in einem privaten Array, das nach dem Kennzeichen indiziert ist. Implementiere:
    • addVehicle(Vehicle $vehicle): void: fügt ein Fahrzeug zur Flotte hinzu
    • findVehicle(string $plate): ?Vehicle: gibt das Fahrzeug oder null zurück
    • getAvailableVehicles(): array: gibt Fahrzeuge zurück, für die canRent() true ist
    • rentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental: Wenn das Fahrzeug nicht gefunden wird, gib "Vehicle not found" zurück; wenn es nicht verfügbar ist, gib "Vehicle is not available" zurück; andernfalls setze das Fahrzeug auf RentedState und gib ein neues Rental-Objekt zurück
    • setMaintenance(string $plate): string: setzt das Fahrzeug auf MaintenanceState; gibt "[plate] set to maintenance" oder "Vehicle not found" zurück
  • main.php: Binde die Dateien RentalService und Customer ein. Du erhältst drei Eingaben: Flottendaten (JSON), Kundendaten (JSON) und Vorgänge (JSON).

    Format des Flotten-JSON:

    [{"type": "car", "plate": "CAR-001", "brand": "Toyota", "rate": 50}, {"type": "van", "plate": "VAN-001", "brand": "Ford", "rate": 80, "mileage_rate": 0.25}]

    Format des Kunden-JSON:

    {"id": 1, "name": "Alice"}

    Format des Vorgänge-JSON:

    [{"op": "available"}, {"op": "rent", "plate": "CAR-001", "days": 3}, {"op": "complete", "plate": "CAR-001"}, {"op": "maintenance", "plate": "VAN-001"}, {"op": "customer_stats"}]

    Erstelle den Vermietungsdienst, füge alle Fahrzeuge zur Flotte hinzu und erstelle den Kunden. Verfolge aktive Mietvorgänge nach Kennzeichen. Verarbeite jeden Vorgang:

    • "available": Gib "Available vehicles: [count]" aus
    • "rent": Miete das Fahrzeug; wenn dies erfolgreich ist, speichere das Rental und gib "Rented [plate] for [days] days" aus; wenn es sich um einen Van handelt, füge miles aus dem Vorgang ein; andernfalls gib die Fehlermeldung aus
    • "complete": Schließe den gespeicherten Mietvorgang für dieses Kennzeichen ab; gib das Ergebnis aus
    • "maintenance": Gib das Ergebnis von setMaintenance() aus
    • "status": Gib für das angegebene Kennzeichen "[plate]: [status]" aus
    • "customer_stats": Gib "[name]: [count] rentals, $[total] spent" aus (2 Dezimalstellen)

    Gib jedes Ergebnis in einer neuen Zeile aus.

Dieses System zeigt, wie das Zustandsmuster die Fahrzeugverfügbarkeit elegant ohne komplexe Bedingungen verwaltet, wie Vererbung eine übersichtliche Fahrzeughierarchie mit polymorpher Preisberechnung erstellt und wie Kapselung die Integrität der Mietdaten während des gesamten Ablaufs schützt.

Probier es selbst

<?php

require_once 'RentalService.php';
require_once 'Customer.php';

// Eingaben lesen
$fleetJson = trim(fgets(STDIN));
$customerJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));

// JSON-Daten parsen
$fleetData = (array)json_decode($fleetJson, true);
$customerData = (array)json_decode($customerJson, true);
$operations = (array)json_decode($operationsJson, true);

// TODO: RentalService-Instanz erstellen

// TODO: Alle Fahrzeuge basierend auf dem Typ zur Flotte hinzufügen:
// - "car" -> new Car(plate, brand, rate)
// - "motorcycle" -> new Motorcycle(plate, brand, rate)
// - "van" -> new Van(plate, brand, rate, mileage_rate)

// TODO: Customer-Instanz aus customerData erstellen

// TODO: Array erstellen, um aktive Vermietungen nach plate zu verfolgen
$activeRentals = [];

// TODO: Jede Operation verarbeiten und Ergebnisse ausgeben:
// - "available": Print "Available vehicles: [count]"
// - "rent": Fahrzeug mieten, Rental speichern falls erfolgreich, Ergebnis ausgeben
// - "complete": Die Vermietung abschließen, Ergebnis ausgeben
// - "maintenance": Wartung setzen, Ergebnis ausgeben
// - "status": "[plate]: [status]" ausgeben
// - "customer_stats": "[name]: [count] rentals, $[total] spent" ausgeben

foreach ($operations as $op) {
    $operation = (array)$op;
    $opType = $operation['op'];
    
    // TODO: Jeden Operationstyp behandeln
    switch ($opType) {
        case 'available':
            // TODO: Print available vehicle count
            break;
        case 'rent':
            // TODO: Fahrzeug mieten und Ergebnis ausgeben
            break;
        case 'complete':
            // TODO: Miete abschließen und Ergebnis ausgeben
            break;
        case 'maintenance':
            // TODO: Wartung setzen und Ergebnis ausgeben
            break;
        case 'status':
            // TODO: Fahrzeugstatus ausgeben
            break;
        case 'customer_stats':
            // TODO: Kundenstatistiken ausgeben
            break;
    }
}

?>

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-PHP-Compiler