איך ליצור טעינה אוטומטית לקבוצת מחלקות
נניח שאתם בונים קבוצה של מחלקות שעושות שימוש אחת בשניה ואתם רוצים להפיץ אותם כספרייה כללית לטיפול במשהו
כל פעם אתם צריכים לדאוג שהמחלקות יהיו טעונות ולוודא שהם זמינות כאב ראש לא קטן נכון ? אז זהו שלא ממש הנה פתרון אלגנטי שיעשה לכם חיים קלים…..
מי שקורא בבלוג יודע שכבר כתבתי על הנושא הזה בפוסט של חיסכון בזיכרון באמצעות Object Registry וטעינה אוטומטית של מחלקות
אבל הפתרון שמוצע שם נכון למקרה שאתם מפיצים מערכת שלמה ושולטים בכל ה AUTOLOAD של המערכת.
בימים אלה אני בונה מחלקה שבונה טפסים אוטומטיים וככזאת היא צריכה להיות גמישה עם אפשרות להוסיף (תאורתית) אין סוף אלמנטים ולכן החלטתי שכל אלמנט הוא מחלקה בקובץ נפרד שמרחיבה את הבסיס
מה שיוצא זה תיקייה שמכילה הרבה מאד קבצים ובשביל להשתמש בכל הסוגים של האלמנטים אני צריך או לטעון את כל הקבצים (רעיון גרוע מאד , אם אני צריך להשתמש באלמנט אחד אין טעם להשתמש ב 900 האחרים)
או פשוט לטעון את הקבצים באופן אוטומטי אז איך עושים את זה ?
קודם כל מחליטים על שם בסיסי שמייצג את הקבוצה של המחלקות שלנו במקרה שלי wsForm , כלומר כל המחלקות מתחילות ב wsForm בשם שלהם.
עכשיו יוצרים קובץ פשוט שנקרא לו wsFormAutoloader.php והוא בעצם ידאג לכל הנושא של הטעינה והוא נראה בערך ככה :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class wsFormAutoloader { static public function register() { ini_set('unserialize_callback_func', 'spl_autoload_call'); spl_autoload_register(array(new self, 'autoload')); } public function autoload($class) { if (0 !== strpos($class, 'wsForm')) { return false; } $class_real_path = dirname(__FILE__).'/'.$class.'.php'; if (file_exists($class_real_path)) { require $class_real_path; } else { trigger_error('Cant autoload class : '.$class.' From : '.$class_real_path); return false; } return true; } } |
הסבר קצר :
הפונקציה register בעצם מודיע ל autoloader של PHP להתחשב במחלקה ולנסות לגשת לקבצים גם דרכה.
הפונקציה autoload בעצם בודקת אם השם של ה class מתחיל ב wsForm , אם לא אז הוא לא שייך לקבוצה והיא מחזירה false כלומר שאין לה אותה , אם כן היא מנסה לטעון את הקובץ
עכשיו בשביל לקרוא קבצים נחוצים אני פשוט צריך לעשות משהו כזה :
1 2 3 4 5 6 | require_once('./wsForm/wsFormAutoloader.php'); wsFormAutoloader::register(); $form = new wsForm(); $form_Field = new wsFormField_Input(); |
מה שקרה בעצם זה שטענו את ה autoloader ומפה בעצם כל קריאה ל new classname המערכת מחפשת את הקובץ המתאים וטוענת אותו.
וזה הכל.
הערה : שימו לב שכל הקבצים צריכים להיות באותה תיקייה , אם אתם רוצים לשים אותם גם בתתי תיקיות תצטרכו לערוך את הפונקציה של ה autoload בשביל להתמודד עם זה
תהנו
על מנת שהיא תוכל להיות רחבה מספיק ואני אוכל להוסיף אין סוף אלמנטים אני רוצה את הגמישות להעלות קובץ ל
אחלה רעיון ואחלה פטנט. רוב הפיתוח שאני עושה הוא בדרופל אז ככה שלא יוצא לי לכתוב מחלקות כמעט בכלל (דרופל הוא עדיין לא מונחה עצמים) אבל הרעיון עצמו מגניב ושימושי גם במקומות אחרים.
הקוד הזה נראה לי מוכר מאיפשהו…. Symfony?
קרוב , ראיתי את הרעיון בפעם הראשונה ב doctrine-porject אחרי זה ראיתי אותו ביותר פשטות ב components.symfony
התאים לי בול לצרכים שלי (wsForm זה מחלקה אמיתית) חסך לי המון ובגלל זה כתבתי עליו
לגבי Symfony עדיין לא הצלחתי לעבוד איתה כמו שצריך
תודה חבל שלו ראיתי את זה לפני חודשים שברתי תראש שעות