Fahrzeugvermietung
Teil des Abschnitts Objektorientierte Programmierung der PHP-Journey von Coddy — Lektion 91 von 91.
Aufgabe
EinfachLassen Sie uns ein Vehicle Rental Service System bauen, das eine Fahrzeugflotte verwaltet, Kundenvermietungen verfolgt und die Preise basierend auf dem Fahrzeugtyp berechnet. Diese umfassende Herausforderung vereint Vererbung, Interfaces, Kapselung und das State-Pattern, um eine realistische Anwendung für ein Vermietungsunternehmen zu erstellen.
Sie werden Ihren Code über sieben Dateien organisieren:
VehicleState.php— Definieren Sie einVehicleStateInterface, das die verschiedenen Zustände darstellt, in denen sich ein Fahrzeug befinden kann. Fügen Sie zwei Methoden hinzu:getStatus(): stringundcanRent(): bool. Erstellen Sie dann drei Klassen, die dieses Interface implementieren:AvailableState— gibt"Available"undtruezurückRentedState— gibt"Rented"undfalsezurückMaintenanceState— gibt"Maintenance"undfalsezurück
Vehicle.php— Binden Sie die VehicleState-Datei ein. Erstellen Sie eine abstrakte KlasseVehiclemit Constructor Promotion fürlicensePlate(string, public readonly),brand(string, public readonly) unddailyRate(float, protected). Speichern Sie den aktuellen Zustand in einer privaten Eigenschaft, standardmäßigAvailableState. Implementieren Sie:getState(): VehicleState— gibt den aktuellen Zustand zurücksetState(VehicleState $state): void— ändert den ZustandgetStatus(): string— delegiert angetStatus()des ZustandscanRent(): bool— delegiert ancanRent()des Zustandsabstract calculateCost(int $days): float— jeder Fahrzeugtyp berechnet die Kosten unterschiedlichgetType(): string— gibt den Klassennamen mittelsstatic::classzurück
Vehicles.php— Binden Sie die Vehicle-Datei ein. Erstellen Sie drei konkrete Fahrzeugklassen:Car— erweitert Vehicle;calculateCost()gibtdailyRate * dayszurückMotorcycle— erweitert Vehicle;calculateCost()gibtdailyRate * days * 0.8zurü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— Erstellen Sie eine KlasseCustomermit Constructor Promotion fürid(int, public readonly) undname(string, public readonly). Verfolgen Sie die Miethistorie in einem privaten Array. Implementieren Sie:addRental(string $vehiclePlate, float $cost): void— fügt einen Eintrag zur Historie hinzugetRentalCount(): int— gibt die Anzahl der Vermietungen zurückgetTotalSpent(): float— gibt die Summe aller Mietkosten zurück
Rental.php— Binden Sie die Vehicle- und Customer-Dateien ein. Erstellen Sie eine KlasseRental, die einen Kunden mit einem Fahrzeug verknüpft. Nutzen Sie Constructor Promotion fürcustomer(Customer, public readonly),vehicle(Vehicle, public readonly),days(int, private) und optionalmiles(int, private, Standard 0). Implementieren Sie:calculateTotal(): float— wenn das Fahrzeug ein Van ist, übergeben Sie miles ancalculateCost(); andernfalls übergeben Sie nur dayscomplete(): string— berechnet die Gesamtsumme, fügt sie der Historie des Kunden hinzu, setzt das Fahrzeug aufAvailableStateund gibt"Rental completed: $[total]"zurück (2 Dezimalstellen)
RentalService.php— Binden Sie die Rental- und Vehicles-Dateien ein. Erstellen Sie eine KlasseRentalService, die die Flotte verwaltet. Speichern Sie Fahrzeuge in einem privaten Array, indiziert nach dem Kennzeichen (license plate). Implementieren Sie:addVehicle(Vehicle $vehicle): void— fügt ein Fahrzeug zur Flotte hinzufindVehicle(string $plate): ?Vehicle— gibt das Fahrzeug oder null zurückgetAvailableVehicles(): array— gibt Fahrzeuge zurück, bei denencanRent()wahr istrentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental— wenn das Fahrzeug nicht gefunden wird, geben Sie"Vehicle not found"zurück; wenn es nicht verfügbar ist, geben Sie"Vehicle is not available"zurück; andernfalls setzen Sie das Fahrzeug aufRentedStateund geben ein neues Rental-Objekt zurücksetMaintenance(string $plate): string— setzt das Fahrzeug aufMaintenanceState; geben Sie"[plate] set to maintenance"oder"Vehicle not found"zurück
main.php— Binden Sie die RentalService- und Customer-Dateien ein. Sie erhalten drei Eingaben: Flottendaten (JSON), Kundendaten (JSON) und Operationen (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 Operationen-JSON:
[{"op": "available"}, {"op": "rent", "plate": "CAR-001", "days": 3}, {"op": "complete", "plate": "CAR-001"}, {"op": "maintenance", "plate": "VAN-001"}, {"op": "customer_stats"}]Erstellen Sie den Rental Service, fügen Sie alle Fahrzeuge zur Flotte hinzu und erstellen Sie den Kunden. Behalten Sie aktive Vermietungen pro Kennzeichen im Auge. Verarbeiten Sie jede Operation:
"available"— Geben Sie"Available vehicles: [count]"aus"rent"— Vermieten Sie das Fahrzeug; falls erfolgreich, speichern Sie das Rental-Objekt und geben Sie"Rented [plate] for [days] days"aus; falls es ein Van ist, beziehen Sie miles aus der Operation mit ein; andernfalls geben Sie die Fehlermeldung aus"complete"— Schließen Sie die gespeicherte Vermietung für dieses Kennzeichen ab; geben Sie das Ergebnis aus"maintenance"— Geben Sie das Ergebnis vonsetMaintenance()aus"status"— Geben Sie"[plate]: [status]"für das angegebene Kennzeichen aus"customer_stats"— Geben Sie"[name]: [count] rentals, $[total] spent"aus (2 Dezimalstellen)
Geben Sie jedes Ergebnis in einer neuen Zeile aus.
Dieses System zeigt, wie das State-Pattern die Fahrzeugverfügbarkeit elegant ohne komplexe Bedingungen handhabt, wie Vererbung eine saubere Fahrzeughierarchie mit polymorpher Preisgestaltung schafft und wie Kapselung die Integrität der Mietdaten während des gesamten Workflows 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 Kennzeichen zu verfolgen
$activeRentals = [];
// TODO: Jede Operation verarbeiten und Ergebnisse ausgeben:
// - "available": "Available vehicles: [count]" ausgeben
// - "rent": Fahrzeug mieten, Rental speichern falls erfolgreich, Ergebnis ausgeben
// - "complete": 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 verarbeiten
switch ($opType) {
case 'available':
// TODO: Anzahl der verfügbaren Fahrzeuge ausgeben
break;
case 'rent':
// TODO: Fahrzeug mieten und Ergebnis ausgeben
break;
case 'complete':
// TODO: Vermietung 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
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas $this-SchlüsselwortMethodenEigenschaftenKonstruktor (__construct)Destruktor (__destruct)Rückblick - Einfacher Taschenrechner4Vererbung
Grundlagen der VererbungDas parent:: SchlüsselwortMethoden überschreibenDas final SchlüsselwortAbstrakte KlassenZusammenfassung – Mitarbeiter-Hierarchie7Kapselung
Public, Protected, PrivateZugriffsmodifikatoren im DetailGetter und SetterInformation HidingConstructor Promotion (8.0)Zusammenfassung – Studentenverwaltungssystem2Namensräume & Autoloading
Einführung in NamensräumeDas use-SchlüsselwortPSR-4 Autoloading-StandardComposer AutoloaderZusammenfassung – Organisiertes Projekt5Interfaces & Verträge
Einführung in InterfacesInterfaces implementierenMehrfache Interface-ImplementierungInterface vs. Abstrakte KlasseType Hinting mit InterfacesZusammenfassung – Formen-Rechner8Magische Methoden
Einführung in magische Methoden__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Objekt-Klonen__serialize & __unserializeZusammenfassung - Eigene Collection11Typsystem & Fehlerbehandlung
TypdeklarationenNullable-TypenUnion- & Intersection-TypenException-KlassenEigene Exception-HierarchieTry, Catch, FinallyZusammenfassung - Formular-Validator14Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Klasseneigenschaften
Instanz- vs. statische EigenschaftenKonstanten in KlassenStatische Methoden & EigenschaftenPrivate & geschützte EigenschaftenReadonly-Eigenschaften (PHP 8.1)Zusammenfassung – Bankkonto-Manager6Polymorphismus
Method Overriding erneut betrachtetPolymorphismus über InterfacesType Hinting & Union TypesLate Static BindingZusammenfassung – Payment Processor9Traits
Einführung in TraitsVerwendung mehrerer TraitsKonfliktlösung bei TraitsAbstrakte Methoden in TraitsTraits vs. Vererbung12Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster15Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung