Faragiri

همهٔ زبان‌ها

آموزش شی‌گرایی در PHP PHP

یک متد با یک نام، هم در والد و هم در تریت. چیزی که اجرا می‌شود نسخه تریت است، و دلیلش این است که تریت پیش از وراثت داخل کلاس کپی می‌شود.

۴بخش
۳دقیقه خواندن
۴عمق

یک نام متد

ترتیبی که PHP یک متد را در آن پیدا می‌کند

جست‌وجو از مرکز شروع می‌شود و اولین لایه‌ای که متد را داشته باشد برنده است؛ لایه‌های بیرونی‌تر دیگر نگاه نمی‌شوند.

  1. متد خود کلاسمتد خود کلاسهرچه در بدنه همین کلاس نوشته شده، و همیشه برنده است
  2. ۰۲متد تریتهنگام کامپایل کپی می‌شود، پس مثل متد خود کلاس رفتار می‌کند
  3. ۰۳متد والدتنها وقتی می‌رسد که دو لایه بالا آن نام را نداشته باشند
  4. ۰۴متد جادوییآخرین راه، و جایی که خطای نام به یک رفتار خاموش تبدیل می‌شود

این حلقه‌ها فقط درباره پیدا کردن نام‌اند. تعارض دو تریت اصلا در این ترتیب حل نمی‌شود و پیش از اجرا خطای کشنده می‌دهد.

یک والد که متد nam دارد، یک تریت که همان متد را دارد، و یک فرزند که از والد ارث می‌برد و تریت را هم استفاده می‌کند. چیزی که اجرا می‌شود نسخه تریت است.

دلیلش این است که تریت وراثت نیست: محتوایش هنگام کامپایل داخل خود کلاس کپی می‌شود، پس مثل متدی است که خودتان در همان کلاس نوشته باشید و طبیعتا از والد جلو می‌زند. ترتیب کامل هم همین را می‌گوید: متد خود کلاس برنده است، بعد تریت، و بعد والد. اگر همان فرزند خودش متد را بنویسد، نسخه خودش اجرا می‌شود.

یک پیامد که کمتر انتظارش را دارند: دو تریت که متدی با یک نام بدهند خطای کشنده می‌سازند و برنامه اصلا اجرا نمی‌شود. برخلاف وراثت چندگانه در زبان‌های دیگر، اینجا هیچ ترتیبی برای حل تعارض فرض نمی‌شود و باید صریح انتخاب کنید.

سازنده‌ای که فیلدها را هم می‌سازد

در PHP امروزی، نوشتن سطح دسترسی روی پارامتر سازنده، همان‌جا فیلد را هم اعلام و مقداردهی می‌کند. یعنی یک کلاس داده به یک سطر جمع می‌شود و دیگر لازم نیست هر نام سه بار نوشته شود.

و در محل ساخت، آرگومان نام‌دار خوانایی را عوض می‌کند: new Kar(ref: "YZ-118", kashi: 240) از دیدن دو مقدار پشت سر هم بدون نامشان بسیار بهتر است، و ترتیبشان هم دیگر مهم نیست. هر دو ویژگی از PHP 8 در دسترس‌اند.

فضای نام و بارگذاری خودکار

فضای نام فقط یک پیشوند برای نام کلاس است و هیچ ربطی به پوشه ندارد. چیزی که آن دو را به هم می‌بندد یک قرارداد است که می‌گوید نام کلاس با مسیر فایل بخواند، و همان قرارداد است که به بارگذار خودکار اجازه می‌دهد فایل را پیدا کند بی‌آنکه چیزی وارد کنید.

خطای «کلاس پیدا نشد» تقریبا همیشه یعنی یکی از سه چیز: نام فایل با نام کلاس نمی‌خواند، بزرگی و کوچکی حروف نمی‌خواند، یا نگاشت فضای نام در فایل تنظیمات به‌روز نشده. مورد دوم روی مک و ویندوز پنهان می‌ماند و روی سرور لینوکسی بیرون می‌زند. تنظیم همان نگاشت کار وابستگی، نسخه، و پوشه‌ای که بسته‌ها در آن می‌نشینند است.

جایی که کار گیر می‌کند، کد بدون کلاس است

بخش بزرگی از کد PHP که در ایران نگهداری می‌شود از دوره‌ای مانده که هر فایل یک صفحه بود و همه چیز در سطح بالا نوشته می‌شد. کسی که در آن کد کار می‌کند شی‌گرایی را در حد نحو می‌داند و هیچ‌وقت لازم نشده استفاده‌اش کند. مرزی که واقعا ارزش دارد اول برداشته شود، جدا کردن منطق از خروجی است: هر فایلی که هم کوئری می‌زند و هم HTML چاپ می‌کند نه قابل آزمون است و نه قابل استفاده دوباره. لازم نیست کل پروژه بازنویسی شود؛ کافی است هر بار که فایلی را باز می‌کنید، محاسبه‌اش را به یک کلاس ببرید و فایل فقط چاپ کند.

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶، نوع‌های ویژگی و پارامتر سازنده و شمارش‌ها همه در PHP 8.4 در دسترس‌اند و رایگان؛ شمارش جای ثابت‌های کلاسی را گرفته که فقط رشته بودند و هیچ بررسی‌ای نداشتند. برای گرفتن خطاهایی که خود زبان درباره‌شان ساکت است، PHPStan تحلیل ایستا انجام می‌دهد و متن‌باز است؛ روی کد قدیمی از سطح پایین شروع کنید و بالا ببرید، وگرنه هزاران خطا می‌گیرید و کنارش می‌گذارید.

پرسش بعدی این است که وقتی این کلاس‌ها به یک ساختار کامل تبدیل شدند، فریم‌ورک چه چیزی از آن‌ها می‌خواهد، که مسیریابی، مدل داده، و نظرهای خودِ فریم‌ورک است. و ترتیب حل متد که این صفحه نشان داد، شکل عمومی‌اش در به اشتراک گذاشتن رفتار، و جایی که تله می‌شود است.

کنار این

بالای این