namespace ב-PHP שם מחלקות, פונקציות וקבועים תחת קידומת כך שהשמות שלהם לא יכולים להתנגש עם השמות של מישהו אחר. מצהירים עליו עם namespace App\Models; כפקודה הראשונה בקובץ, וקבצים אחרים מתייחסים למחלקה כ-\App\Models\User, או מייבאים אותה עם use App\Models\User; וכותבים רק User.
בתוך ה-namespace, User פירושו App\Models\User. User::class נותן את השם המלא כמחרוזת בלי ליצור שום דבר, וזה שימושי ללוגים ול-autoloaders.
שני namespaces בקובץ אחד
פרויקט אמיתי שם namespace אחד בכל קובץ. בהדגמה עצמאית, קובץ אחד יכול להחזיק כמה namespaces כשכל אחד עטוף בסוגריים מסולסלים. קוד שלא שייך לשום namespace נכנס ל-namespace { }:
שתי מחלקות בשם Order חיות זו לצד זו כי השמות המלאים שלהן שונים. זו בדיוק הבעיה ש-namespaces פותרים ברגע שמתקינים ספריות: ה-Order שלכם, ה-Order של ספריית תשלומים וה-Order של ספריית PDF כבר לא מתנגשים.
ייבוא עם use וכינוי עם as
כתיבה של \Shop\Order בכל מקום רועשת. use בראש קובץ (או בלוק namespace) מייבא שם כך שאפשר להשתמש בצורה הקצרה. כששני ייבואים היו מסתיימים באותו שם קצר, as נותן לאחד מהם שם אחר:
use רק יוצר שם קצר לשאר הקובץ. הוא לא טוען קובץ ולא מריץ קוד, והוא עובד אותו דבר בין אם המחלקה כבר קיימת ובין אם לא. מותרים גם ייבואים מקובצים: use Shop\{Order, Invoice};.
use function ו-use const
פונקציות וקבועים ב-namespace מיובאים עם use function ו-use const:
מחלקות גלובליות צריכות לוכסן הפוך
בתוך namespace, שם מחלקה בלי קידומת מתפרש ביחס ל-namespace הזה, ולכן new DateTime() בתוך namespace App; מחפש את App\DateTime. פונקציות וקבועים שונים: אם App\strlen לא קיימת, PHP נופלת חזרה ל-strlen הגלובלית. מחלקות אף פעם לא נופלות חזרה.
ה-catch (\Error $e) היה צריך לוכסן הפוך מאותה סיבה: בלעדיו PHP הייתה מחפשת את App\Error, אף פעם לא מתאימה לשגיאה האמיתית, והסקריפט היה נעצר עם Error שלא נתפס. תקנו את זה או עם לוכסן הפוך מוביל, כמו למעלה, או עם use DateTime; בראש הקובץ. אותו דבר חל על \Exception, על \Throwable ועל כל מחלקה מובנית אחרת; ראו try catch על תפיסה שלהן.
טעינה אוטומטית ו-PSR-4
בפרויקט, כל מחלקה חיה בקובץ משלה, ונתיב הקובץ עוקב אחרי ה-namespace. PSR-4 היא המוסכמה: קידומת של namespace ממופה לתיקיית בסיס, ושאר השם הופך לנתיב. autoloader שנרשם עם spl_autoload_register() טוען אז קובץ מחלקה בפעם הראשונה שמשתמשים במחלקה. הבלוק הזה כותב שני קובצי מחלקות לדיסק וטוען אותם אוטומטית:
כל קובץ מחלקה נטען פעם אחת, ברגע שהמחלקה נחוצה לראשונה. בפרויקטים אמיתיים לא כותבים את הפונקציה הזו בעצמכם: Composer מייצר אותה מכמה שורות ב-composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
אחרי composer dump-autoload, require __DIR__ . '/vendor/autoload.php'; אחד בתחילת סקריפט הכניסה שלכם טוען כל מחלקה של App\... לפי דרישה.
כללי namespace שגורמים לשגיאות
namespaceחייבת להיות הפקודה הראשונה בקובץ. רקdeclare(strict_types=1);והערות יכולים לבוא לפניה.- ייבואי
useהם לכל קובץ בנפרד. ייבוא של מחלקה ב-index.phpלא גורם לשם הקצר לעבוד בתוך קובץ שנכלל; כל קובץ צריך שורותuseמשלו. useשייכת לרמה העליונה של הקובץ או של בלוק ה-namespace. בתוך גוף של מחלקה, ל-useיש משמעות אחרת: היא מושכת פנימה trait.- מחרוזות אף פעם לא מתפרשות:
$class = 'User'; new $class();מחפש אתUserהגלובלית. שמרו את השם המלא, רצוי עםUser::class.
הכלל האחרון שווה בדיקה מהירה:
שאלות נפוצות
מה זה namespace ב-PHP?
קידומת שמקבצת מחלקות, ממשקים, פונקציות וקבועים קשורים, כמו תיקייה לשמות. namespace App\Models; בראש קובץ שם את המחלקה User שלו ב-App\Models\User, כך שהיא לא יכולה להתנגש עם User של ספרייה אחרת.
מה use עושה ב-PHP?
use App\Models\User; בראש קובץ מאפשר לכתוב User במקום השם המלא \App\Models\User בקובץ הזה. הוא לא טוען ולא כולל שום דבר; טעינת קובץ המחלקה היא העבודה של ה-autoloader. use ... as Alias; בוחר שם קצר אחר.
למה אני מקבל Class not found בתוך namespace?
בתוך namespace App; שם מחלקה בלי קידומת מתפרש ביחס ל-namespace, ולכן new DateTime() מחפש את App\DateTime. כתבו new \DateTime() או הוסיפו use DateTime; בראש הקובץ. פונקציות וקבועים נופלים חזרה למרחב הגלובלי אוטומטית, מחלקות לא.
מה הלוכסן ההפוך לפני שם מחלקה ב-PHP?
לוכסן הפוך מוביל הופך את השם למלא, שמתחיל מהמרחב הגלובלי: \Exception הוא תמיד ה-Exception המובנה של PHP, בכל namespace שבו הקוד נמצא. בלעדיו, השם מתפרש ביחס ל-namespace הנוכחי ולייבואים של use.
מה הקשר בין namespaces לתיקיות ול-PSR-4?
PHP עצמה לא קושרת namespaces לתיקיות. PSR-4 היא המוסכמה שעושה את זה: קידומת כמו App\ ממופה לתיקייה כמו src/, ולכן App\Models\User נמצאת ב-src/Models/User.php. ה-autoloader של Composer עוקב אחריה, ולכן השניים בדרך כלל תואמים.