שירות השכרת כלי רכב
חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 91 מתוך 91.
אתגר
קלבואו נבנה מערכת Vehicle Rental Service שמנהלת צי של כלי רכב, עוקבת אחר השכרות של לקוחות ומחשבת מחירים בהתאם לסוג הרכב. האתגר המקיף הזה משלב ירושה, ממשקים, כימוס ואת תבנית State כדי ליצור יישום מציאותי לניהול עסק להשכרת כלי רכב.
תארגנו את הקוד שלכם בשבעה קבצים:
VehicleState.php: הגדירו ממשקVehicleStateשמייצג את המצבים השונים שבהם רכב יכול להיות. כללו שתי מתודות:getStatus(): stringו-canRent(): bool. לאחר מכן צרו שלוש מחלקות שמממשות את הממשק הזה:AvailableState: מחזירה"Available"ו-trueRentedState: מחזירה"Rented"ו-falseMaintenanceState: מחזירה"Maintenance"ו-false
Vehicle.php: כללו את הקובץ VehicleState. צרו מחלקה מופשטתVehicleעם קידום פרמטרים בבנאי עבורlicensePlate(מחרוזת, public readonly),brand(מחרוזת, public readonly) ו-dailyRate(מספר עשרוני, protected). שמרו את המצב הנוכחי במאפיין פרטי, עם ברירת מחדל שלAvailableState. ממשו:getState(): VehicleState: מחזירה את המצב הנוכחיsetState(VehicleState $state): void: משנה את המצבgetStatus(): string: מעבירה את הקריאה ל-getStatus()של המצבcanRent(): bool: מעבירה את הקריאה ל-canRent()של המצבabstract calculateCost(int $days): float: כל סוג רכב מחשב את העלות באופן שונהgetType(): string: מחזירה את שם המחלקה באמצעותstatic::class
Vehicles.php: כללו את קובץ Vehicle. צרו שלוש מחלקות קונקרטיות לכלי רכב:Car: יורשת מ-Vehicle;calculateCost()מחזירהdailyRate * daysMotorcycle: יורשת מ-Vehicle;calculateCost()מחזירהdailyRate * days * 0.8(הנחה של 20%)Van: יורשת מ-Vehicle עם פרמטר נוסף$mileageRate(מספר עשרוני);calculateCost(int $days, int $miles = 0)מחזירה(dailyRate * days) + (mileageRate * miles)
Customer.php: צרו מחלקהCustomerעם קידום פרמטרים בבנאי עבורid(מספר שלם, public readonly) ו-name(מחרוזת, public readonly). עקבו אחר היסטוריית ההשכרות במערך פרטי. ממשו:addRental(string $vehiclePlate, float $cost): void: מוסיפה להשכרות בהיסטוריהgetRentalCount(): int: מחזירה את מספר ההשכרותgetTotalSpent(): float: מחזירה את הסכום של כל עלויות ההשכרה
Rental.php: כללו את הקבצים Vehicle ו-Customer. צרו מחלקהRentalשמקשרת לקוח לרכב. השתמשו בקידום פרמטרים בבנאי עבורcustomer(Customer, public readonly),vehicle(Vehicle, public readonly),days(מספר שלם, private) ואפשר גםmiles(מספר שלם, private, ברירת מחדל 0). ממשו:calculateTotal(): float: אם הרכב הוא Van, העבירו את miles אלcalculateCost(); אחרת העבירו רק את dayscomplete(): string: מחשבת את הסכום הכולל, מוסיפה אותו להיסטוריה של הלקוח, משנה את מצב הרכב ל-AvailableState ומחזירה"Rental completed: $[total]"(2 ספרות אחרי הנקודה העשרונית)
RentalService.php: כללו את הקבצים Rental ו-Vehicles. צרו מחלקהRentalServiceשמנהלת את צי הרכב. שמרו את כלי הרכב במערך פרטי שממוּפתח לפי לוחית הרישוי. ממשו:addVehicle(Vehicle $vehicle): void: מוסיפה את הרכב לציfindVehicle(string $plate): ?Vehicle: מחזירה את הרכב או nullgetAvailableVehicles(): array: מחזירה את כלי הרכב שעבורםcanRent()הוא truerentVehicle(Customer $customer, string $plate, int $days, int $miles = 0): string|Rental: אם הרכב לא נמצא, החזירו"Vehicle not found"; אם הוא לא זמין, החזירו"Vehicle is not available"; אחרת שנו את מצב הרכב ל-RentedState והחזירו אובייקט Rental חדשsetMaintenance(string $plate): string: משנה את מצב הרכב ל-MaintenanceState; מחזירה"[plate] set to maintenance"או"Vehicle not found"
main.php: כללו את הקבצים RentalService ו-Customer. תקבלו שלוש קלטים: נתוני צי הרכב (JSON), נתוני הלקוח (JSON) ופעולות (JSON).פורמט JSON של צי הרכב:
[{"type": "car", "plate": "CAR-001", "brand": "Toyota", "rate": 50}, {"type": "van", "plate": "VAN-001", "brand": "Ford", "rate": 80, "mileage_rate": 0.25}]פורמט JSON של הלקוח:
{"id": 1, "name": "Alice"}פורמט JSON של הפעולות:
[{"op": "available"}, {"op": "rent", "plate": "CAR-001", "days": 3}, {"op": "complete", "plate": "CAR-001"}, {"op": "maintenance", "plate": "VAN-001"}, {"op": "customer_stats"}]צרו את שירות ההשכרה, הוסיפו את כל כלי הרכב לצי וצרו את הלקוח. עקבו אחר ההשכרות הפעילות לפי לוחית הרישוי. עבדו על כל פעולה:
"available": הדפיסו"Available vehicles: [count]""rent": השכירו את הרכב; אם ההשכרה הצליחה, שמרו את ה-Rental והדפיסו"Rented [plate] for [days] days"; אם הרכב הוא Van, כללו את מספר המיילים מהפעולה; אחרת הדפיסו את הודעת השגיאה"complete": השלימו את ההשכרה השמורה עבור לוחית הרישוי הזו; הדפיסו את התוצאה"maintenance": הדפיסו את התוצאה שלsetMaintenance()"status": הדפיסו"[plate]: [status]"עבור לוחית הרישוי הנתונה"customer_stats": הדפיסו"[name]: [count] rentals, $[total] spent"(2 ספרות אחרי הנקודה העשרונית)
הדפיסו כל תוצאה בשורה חדשה.
המערכת מדגימה כיצד תבנית State מטפלת באופן אלגנטי בזמינות כלי הרכב ללא תנאים מורכבים, כיצד ירושה יוצרת היררכיה מסודרת של כלי רכב עם תמחור פולימורפי, וכיצד כימוס מגן על שלמות נתוני ההשכרה לאורך כל תהליך העבודה.
נסו בעצמכם
<?php
require_once 'RentalService.php';
require_once 'Customer.php';
// קרא את הקלטים
$fleetJson = trim(fgets(STDIN));
$customerJson = trim(fgets(STDIN));
$operationsJson = trim(fgets(STDIN));
// פענח נתוני JSON
$fleetData = (array)json_decode($fleetJson, true);
$customerData = (array)json_decode($customerJson, true);
$operations = (array)json_decode($operationsJson, true);
// TODO: צור מופע של RentalService
// TODO: הוסף את כל כלי הרכב לצי לפי הסוג:
// - "car" -> new Car(plate, brand, rate)
// - "motorcycle" -> new Motorcycle(plate, brand, rate)
// - "van" -> new Van(plate, brand, rate, mileage_rate)
// TODO: צור מופע של Customer מתוך customerData
// TODO: צור מערך למעקב אחר השכרות פעילות לפי לוחית רישוי
$activeRentals = [];
// TODO: עבד כל פעולה והדפס את התוצאות:
// - "available": הדפס "Available vehicles: [count]"
// - "rent": השכר רכב, שמור את Rental אם הפעולה הצליחה, והדפס את התוצאה
// - "complete": השלם את ההשכרה והדפס את התוצאה
// - "maintenance": הגדר מצב תחזוקה והדפס את התוצאה
// - "status": הדפס "[plate]: [status]"
// - "customer_stats": הדפס "[name]: [count] rentals, $[total] spent"
foreach ($operations as $op) {
$operation = (array)$op;
$opType = $operation['op'];
// TODO: טפל בכל סוג פעולה
switch ($opType) {
case 'available':
// TODO: הדפס את מספר הרכבים הזמינים
break;
case 'rent':
// TODO: השכר רכב והדפס את התוצאה
break;
case 'complete':
// TODO: השלם את ההשכרה והדפס את התוצאה
break;
case 'maintenance':
// TODO: הגדר מצב תחזוקה והדפס את התוצאה
break;
case 'status':
// TODO: הדפס את מצב הרכב
break;
case 'customer_stats':
// TODO: הדפס את נתוני הלקוח
break;
}
}
?>כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח $thisמתודותמאפייניםבנאי (__construct)הורס (__destruct)חזרה: מחשבון פשוט4ירושה
ירושה בסיסיתמילת המפתח parent::דריסת מתודותמילת המפתח finalמחלקות מופשטותסיכום – היררכיית עובדים7כימוס
ציבורי, מוגן, פרטימפרטי גישה לעומקמתודות גישה ועדכוןהסתרת מידעקידום פרמטרים בבנאי (8.0)סיכום – מערכת רישומי תלמידים2מרחבי שמות וטעינה אוטומטית
מבוא למרחבי שמותמילת המפתח useתקן הטעינה האוטומטית PSR-4הטוען האוטומטי של Composerסיכום – פרויקט מאורגן5ממשקים וחוזים
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםממשק לעומת מחלקה מופשטתרמזי טיפוסים עם ממשקיםסיכום - מחשבון צורות8מתודות קסם
מבוא למתודות קסם__toString ו־__debugInfo__get, __set, __isset, __unset__call ו־__callStatic__clone ושיבוט אובייקטים__serialize ו־__unserializeסיכום – אוסף מותאם אישית3מאפייני מחלקה
מאפייני מופע לעומת מאפיינים סטטייםקבועים במחלקותמתודות ומאפיינים סטטייםמאפיינים פרטיים ומוגניםמאפיינים לקריאה בלבד (PHP 8.1)סיכום – מנהל חשבון בנק6פולימורפיזם
בחינה מחדש של דריסת מתודותפולימורפיזם באמצעות ממשקיםרמזי טיפוסים וטיפוסי איחודקישור סטטי מאוחרסיכום — מעבד תשלומיםתרגלו בעצמכם: קומפיילר PHP אונליין