הזרקת תלויות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 57 מתוך 91.
בשיעור הקודם ראית איך קומפוזיציה מאפשרת ל־Car להכיל אובייקט Engine. אבל יש בעיה ביצירת תלויות בתוך המחלקה — היא הופכת את הקוד לנוקשה וקשה לבדיקה. הזרקת תלויות פותרת זאת על ידי העברת תלויות מבחוץ במקום ליצור אותן בתוך המחלקה.
השוו בין שתי הגישות האלה:
<?php
// ללא DI - התלות נוצרת בפנים
class Car {
private Engine $engine;
public function __construct() {
$this->engine = new Engine(); // צימוד הדוק
}
}
// עם DI - התלות מועברת פנימה
class Car {
public function __construct(private Engine $engine) {}
}
$engine = new Engine();
$car = new Car($engine); // מוזרק מבחוץ
הגישה השנייה היא הזרקת תלויות. ה־Car לא יוצר מנוע משלו — הוא מקבל אחד. לשינוי הפשוט הזה יש יתרונות משמעותיים: אפשר להעביר סוגים שונים של מנועים, להחליף מימושים לצורכי בדיקה, והמחלקה נעשית גמישה יותר.
לגמישות רבה עוד יותר, הזריקו ממשקים במקום מחלקות קונקרטיות:
<?php
interface EngineInterface {
public function start(): string;
}
class Car {
public function __construct(private EngineInterface $engine) {}
public function start(): string {
return $this->engine->start();
}
}
כעת Car עובדת עם כל מחלקה שמממשת את EngineInterface — מנוע בנזין, מנוע חשמלי או דמה לצורכי בדיקה. הניתוק הזה הוא הסיבה לכך שהזרקת תלויות היא עקרון יסודי בכתיבת יישומי PHP שקל לתחזק ולבדוק.
אתגר
קלבואו נבנה מערכת התראות שמדגימה את העוצמה של הזרקת תלויות. במקום לקבוע בקוד מראש איך נשלחות הודעות, תיצרו מערכת גמישה שבה אפשר להחליף בקלות את שיטת המסירה.
תארגנו את הקוד שלכם בארבעה קבצים:
MessageSenderInterface.php: הגדירו ממשק בשםMessageSenderInterfaceעם מתודה יחידהsend(string $recipient, string $message): string. הממשק הזה מגדיר את החוזה שעליו כל שולח הודעות לעמוד.EmailSender.php: צרו מחלקהEmailSenderשמממשת אתMessageSenderInterface. כללו את קובץ הממשק. המתודהsend()צריכה להחזיר את"Email to [recipient]: [message]".NotificationService.php: צרו מחלקהNotificationServiceשמקבלת את התלות שלה דרך הבנאי. כללו את קובץ הממשק. המחלקה צריכה:- לקבל
MessageSenderInterfaceבבנאי באמצעות קידום מאפיינים בבנאי - להכיל מתודה
notify(string $recipient, string $message)שמעבירה את הקריאה לשולח שהוזרק ומחזירה את התוצאה שלו
NotificationServiceתלויה בממשק, ולא במחלקה קונקרטית. פירוש הדבר שאפשר להזריק כל שולח שמממש את הממשק בלי לשנות את השירות.- לקבל
main.php: כללו את הקבצים EmailSender ו-NotificationService. תקבלו שתי קלטים: נמען והודעה. צרוEmailSender, הזריקו אותו אלNotificationService, ואז קראו ל-notify()והדפיסו את התוצאה.
התבנית הזאת שומרת על הגמישות של NotificationService. היא עובדת עם כל שולח שתזריקו לה, בין אם מדובר בדוא"ל, ב-SMS או במשהו שעדיין לא בניתם. השירות לא יוצר את התלויות של עצמו; הוא מקבל אותן מבחוץ.
נסו בעצמכם
<?php
require_once 'EmailSender.php';
require_once 'NotificationService.php';
// קרא את הקלט
$recipient = trim(fgets(STDIN));
$message = trim(fgets(STDIN));
// TODO: צור מופע של EmailSender
// TODO: הזרק אותו ל-NotificationService
// TODO: קרא ל-notify() והדפס את התוצאה
?>השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח $thisמתודותמאפייניםבנאי (__construct)הורס (__destruct)חזרה: מחשבון פשוט4ירושה
ירושה בסיסיתמילת המפתח parent::דריסת מתודותמילת המפתח finalמחלקות מופשטותסיכום – היררכיית עובדים7כימוס
ציבורי, מוגן, פרטימפרטי גישה לעומקמתודות גישה ועדכוןהסתרת מידעקידום פרמטרים בבנאי (8.0)סיכום – מערכת רישומי תלמידים10מושגי OOP מתקדמים
הרכבה לעומת ירושההזרקת תלויותמחלקות אנונימיותטיפוסי Enum (PHP 8.1)סיבים (PHP 8.1)העמקה בשכפול אובייקטיםמחוללים ואיטרטורים2מרחבי שמות וטעינה אוטומטית
מבוא למרחבי שמותמילת המפתח useתקן הטעינה האוטומטית PSR-4הטוען האוטומטי של Composerסיכום – פרויקט מאורגן5ממשקים וחוזים
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםממשק לעומת מחלקה מופשטתרמזי טיפוסים עם ממשקיםסיכום - מחשבון צורות8מתודות קסם
מבוא למתודות קסם__toString ו־__debugInfo__get, __set, __isset, __unset__call ו־__callStatic__clone ושיבוט אובייקטים__serialize ו־__unserializeסיכום – אוסף מותאם אישית3מאפייני מחלקה
מאפייני מופע לעומת מאפיינים סטטייםקבועים במחלקותמתודות ומאפיינים סטטייםמאפיינים פרטיים ומוגניםמאפיינים לקריאה בלבד (PHP 8.1)סיכום – מנהל חשבון בנק6פולימורפיזם
בחינה מחדש של דריסת מתודותפולימורפיזם באמצעות ממשקיםרמזי טיפוסים וטיפוסי איחודקישור סטטי מאוחרסיכום — מעבד תשלומיםתרגלו בעצמכם: קומפיילר PHP אונליין