Servizio di noleggio veicoli
Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 91 di 91.
Sfida
FacileCostruiamo un sistema di noleggio di veicoli che gestisce una flotta di veicoli, tiene traccia dei noleggi dei clienti e calcola i prezzi in base al tipo di veicolo. Questa sfida completa combina ereditarietà, interfacce, incapsulamento e il pattern State per creare un'applicazione realistica per un'attività di noleggio.
Organizzerai il codice in sette file:
VehicleState.php: definisci un'interfacciaVehicleStateche rappresenta i diversi stati in cui può trovarsi un veicolo. Includi due metodi:getStatus(): stringecanRent(): bool. Poi crea tre classi che implementano questa interfaccia:AvailableState: restituisce"Available"etrueRentedState: restituisce"Rented"efalseMaintenanceState: restituisce"Maintenance"efalse
Vehicle.php: includi il file VehicleState. Crea una classe astrattaVehicleusando la promozione delle proprietà del costruttore perlicensePlate(string, public readonly),brand(string, public readonly) edailyRate(float, protected). Memorizza lo stato corrente in una proprietà privata, impostandolo inizialmente suAvailableState. Implementa:getState(): VehicleState: restituisce lo stato correntesetState(VehicleState $state): void: modifica lo statogetStatus(): string: delega agetStatus()dello statocanRent(): bool: delega acanRent()dello statoabstract calculateCost(int $days): float: ciascun tipo di veicolo calcola il costo in modo diversogetType(): string: restituisce il nome della classe usandostatic::class
Vehicles.php: includi il file Vehicle. Crea tre classi concrete di veicoli:Car: estende Vehicle;calculateCost()restituiscedailyRate * daysMotorcycle: estende Vehicle;calculateCost()restituiscedailyRate * days * 0.8(sconto del 20%)Van: estende Vehicle con un parametro aggiuntivo$mileageRate(float);calculateCost(int $days, int $miles = 0)restituisce(dailyRate * days) + (mileageRate * miles)
Customer.php: crea una classeCustomerusando la promozione delle proprietà del costruttore perid(int, public readonly) ename(string, public readonly). Tieni traccia della cronologia dei noleggi in un array privato. Implementa:addRental(string $vehiclePlate, float $cost): void: aggiunge un noleggio alla cronologiagetRentalCount(): int: restituisce il numero di noleggigetTotalSpent(): float: restituisce la somma dei costi di tutti i noleggi
Rental.php: includi i file Vehicle e Customer. Crea una classeRentalche associa un cliente a un veicolo. Usa la promozione delle proprietà del costruttore percustomer(Customer, public readonly),vehicle(Vehicle, public readonly),days(int, private) e, facoltativamente,miles(int, private, valore predefinito 0). Implementa:calculateTotal(): float: se il veicolo è un Van, passa i miles acalculateCost(); altrimenti passa solo i dayscomplete(): string: calcola il totale, lo aggiunge alla cronologia del cliente, imposta lo stato del veicolo su AvailableState e restituisce"Rental completed: $[total]"(2 cifre decimali)
RentalService.php: includi i file Rental e Vehicles. Crea una classeRentalServiceche gestisce la flotta. Memorizza i veicoli in un array privato indicizzato per targa. Implementa:addVehicle(Vehicle $vehicle): void: aggiunge un veicolo alla flottafindVehicle(string $plate): ?Vehicle: restituisce il veicolo oppure nullgetAvailableVehicles(): array: restituisce i veicoli per cuicanRent()è truerentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental: se il veicolo non viene trovato, restituisce"Vehicle not found"; se non è disponibile, restituisce"Vehicle is not available"; altrimenti imposta lo stato del veicolo su RentedState e restituisce un nuovo oggetto RentalsetMaintenance(string $plate): string: imposta lo stato del veicolo su MaintenanceState; restituisce"[plate] set to maintenance"oppure"Vehicle not found"
main.php: includi i file RentalService e Customer. Riceverai tre input: i dati della flotta (JSON), i dati del cliente (JSON) e le operazioni (JSON).Formato del JSON della flotta:
[{"type": "car", "plate": "CAR-001", "brand": "Toyota", "rate": 50}, {"type": "van", "plate": "VAN-001", "brand": "Ford", "rate": 80, "mileage_rate": 0.25}]Formato del JSON del cliente:
{"id": 1, "name": "Alice"}Formato del JSON delle operazioni:
[{"op": "available"}, {"op": "rent", "plate": "CAR-001", "days": 3}, {"op": "complete", "plate": "CAR-001"}, {"op": "maintenance", "plate": "VAN-001"}, {"op": "customer_stats"}]Crea il servizio di noleggio, aggiungi tutti i veicoli alla flotta e crea il cliente. Tieni traccia dei noleggi attivi in base alla targa. Elabora ogni operazione:
"available": stampa"Available vehicles: [count]""rent": noleggia il veicolo; se l'operazione ha esito positivo, memorizza il Rental e stampa"Rented [plate] for [days] days"; se si tratta di un Van, includi i miles dell'operazione; altrimenti stampa il messaggio di errore"complete": completa il noleggio memorizzato per quella targa; stampa il risultato"maintenance": stampa il risultato disetMaintenance()"status": stampa"[plate]: [status]"per la targa specificata"customer_stats": stampa"[name]: [count] rentals, $[total] spent"(2 cifre decimali)
Stampa ogni risultato su una nuova riga.
Questo sistema mostra come il pattern State gestisca elegantemente la disponibilità dei veicoli senza condizioni complesse, come l'ereditarietà crei una gerarchia di veicoli chiara con prezzi polimorfici e come l'incapsulamento protegga l'integrità dei dati di noleggio durante tutto il flusso di lavoro.
Provalo tu
<?php
require_once 'RentalService.php';
require_once 'Customer.php';
// Leggi gli input
$fleetJson = trim(fgets(STDIN));
$customerJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));
// Analizza i dati JSON
$fleetData = (array)json_decode($fleetJson, true);
$customerData = (array)json_decode($customerJson, true);
$operations = (array)json_decode($operationsJson, true);
// TODO: Crea un'istanza di RentalService
// TODO: Aggiungi tutti i veicoli alla flotta in base al tipo:
// - "car" -> new Car(plate, brand, rate)
// - "motorcycle" -> new Motorcycle(plate, brand, rate)
// - "van" -> new Van(plate, brand, rate, mileage_rate)
// TODO: Crea un'istanza di Customer da customerData
// TODO: Crea un array per tenere traccia dei noleggi attivi in base alla targa
$activeRentals = [];
// TODO: Elabora ogni operazione e stampa i risultati:
// - "available": Stampa "Available vehicles: [count]"
// - "rent": Noleggia il veicolo, memorizza Rental se l'operazione riesce e stampa il risultato
// - "complete": Completa il noleggio e stampa il risultato
// - "maintenance": Imposta la manutenzione e stampa il risultato
// - "status": Stampa "[plate]: [status]"
// - "customer_stats": Stampa "[name]: [count] rentals, $[total] spent"
foreach ($operations as $op) {
$operation = (array)$op;
$opType = $operation['op'];
// TODO: Gestisci ogni tipo di operazione
switch ($opType) {
case 'available':
// TODO: Stampa il numero di veicoli disponibili
break;
case 'rent':
// TODO: Noleggia il veicolo e stampa il risultato
break;
case 'complete':
// TODO: Completa il noleggio e stampa il risultato
break;
case 'maintenance':
// TODO: Imposta la manutenzione e stampa il risultato
break;
case 'status':
// TODO: Stampa lo stato del veicolo
break;
case 'customer_stats':
// TODO: Stampa le statistiche del cliente
break;
}
}
?>Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave $thisMetodiProprietàCostruttore (__construct)Distruttore (__destruct)Riepilogo - Calcolatrice semplice4Ereditarietà
Ereditarietà di baseLa parola chiave parent::Sovrascrittura dei metodiLa parola chiave finalClassi astratteRiepilogo - Gerarchia dei dipendenti7Incapsulamento
Pubblico, Protetto, PrivatoApprofondimento sui modificatori di accessoGetter e SetterOccultamento delle informazioniPromozione dei parametri del costruttore (8.0)Riepilogo - Sistema di gestione dei registri degli studenti10Concetti avanzati di programmazione a oggetti
Composizione vs ereditarietàDependency InjectionClassi anonimeEnumerazioni (PHP 8.1)Fibers (PHP 8.1)Approfondimento sulla clonazione degli oggettiGeneratori e iteratori13Modelli di progettazione, parte 2
Modello CommandModello AdapterModello DecoratorModello Template MethodModello StateModello CompositeModello Repository2Namespace e autoloading
Introduzione ai namespaceLa keyword useStandard di autoloading PSR-4Autoloader di ComposerRiepilogo - Progetto organizzato5Interfacce e contratti
Introduzione alle interfacceImplementare le interfacceImplementare più interfacceInterfaccia vs classe astrattaType hinting con le interfacceRiepilogo - Calcolatore di forme8Metodi magici
Introduzione ai metodi magici__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e clonazione degli oggetti__serialize e __unserializeRiepilogo - Collezione personalizzata11Sistema dei tipi e gestione degli errori
Dichiarazioni di tipoTipi nullableTipi unione e intersezioneClassi di eccezioneGerarchia di eccezioni personalizzataTry, Catch, FinallyRiepilogo - Validatore di moduli14Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Proprietà delle classi
Proprietà di istanza e staticheCostanti nelle classiMetodi e proprietà staticiProprietà private e protectedProprietà readonly (PHP 8.1)Riepilogo - Gestore di conti bancari6Polimorfismo
Ridefinizione dei metodi, ripresaPolimorfismo tramite interfacceSuggerimenti sui tipi e tipi UnionBinding statico tardivoRiepilogo - Processore di pagamenti9Tratti
Introduzione ai trattiUtilizzare più trattiRisoluzione dei conflitti tra trattiMetodi astratti nei trattiTratti vs ereditarietà12Design pattern - Parte 1
Introduzione ai design patternPattern SingletonPattern FactoryPattern ObserverPattern Strategy15Sfide finali
Piattaforma di e-learningSistema bancarioSviluppo di un personaggio di giocoServizio di noleggio veicoliEsercitati da solo: Compilatore PHP online