لبهی تیزِ RouteParameter تو Laravel: مدلت رو bind نمیکنه
خلاصهٔ کاملتر
نویسنده (Michael Dyrynda) توضیح میده که اتریبیوتهای container تو Laravel از نسخهی ۱۱ بهعنوان بخشی از قابلیتِ contextual attributesِ سرویس کانتینر اومدن، کنارِ اتریبیوتهایی مثل #[Config]، #[Cache] و #[CurrentUser]. اینها یه مشکل واقعی رو حل میکنن: قبلاً اگه میخواستی به یه مدلِ bindشدهی روت بیرون از امضای کنترلر دسترسی داشته باشی، یا باید request()->route('event') صدا میزدی یا یه انوتیشنِ @var اضافه میکردی که تایپش فقط تو کامنت زندگی میکرد.
#[RouteParameter] به اون مقدار یه جای typeدار میده. بهصورت constructor-promoted و در صورت دلخواه readonly، و ابزارِ کدت هم تایپش رو میفهمه:
public function __construct(
#[RouteParameter('event')] public readonly Event $event,
) {}نویسنده میگه این الگو مخصوصاً تو form requestها وسوسهانگیزه، جایی که ممکنه بخوای مدلِ bindشدهی روت رو تو authorize() یا rules() داشته باشی، و ترجیح میده بهجای method injection، یه بار تعریفش کنه و همهجا استفاده کنه.
ولی اینجا لبهی تیز خودشو نشون میده. طبق مقاله، #[RouteParameter] فقط مقدارِ فعلیِ پارامترِ روت رو میخونه و خودش route model binding انجام نمیده. پس اگه اکشنِ متناظرِ کنترلر به Laravel اطلاعات کافی برای bind کردنِ ضمنیِ {event} نده، ممکنه این اتریبیوت بهجای یه نمونهی مدلِ Event، رشتهی خامِ روت رو دریافت کنه.
نویسنده تعریف میکنه که این مشکل تو یه مثالِ اسباببازی پیش نیومده، بلکه تو پلتفرمِ Laracon AU؛ جایی که چند اکشنِ کنترلر داشته که مدلِ bindشدهی روت فقط برای guard clause و تصمیمِ authorization اونجا بودن، نه بهعنوان بخشی از خودِ اکشن. این حس میداده که کار به قلمروِ form request تعلق داره، چون form request همون اول یه متدِ authorize() داره و بردنِ guard به اونجا کنترلر رو روی مسیرِ موفق متمرکز نگه میداره. جمعبندیِ مقاله اینه که binding ضمنی به امضای متدِ کنترلر وابستهست و صرفِ استفاده از این اتریبیوت تضمین نمیکنه که مدلِ hydrateشده تحویل بگیری.
نکات کلیدی:
- #[RouteParameter] (از Laravel 11) یه جای typeدار برای پارامتر روت میده و جایگزینِ request()->route() و انوتیشن PHPDoc میشه.
- این اتریبیوت فقط مقدارِ فعلیِ پارامتر رو میخونه و خودش route model binding انجام نمیده.
- اگه امضای اکشنِ کنترلر اطلاعات کافی برای bindِ ضمنی نده، ممکنه رشتهی خام بهجای مدل دستت بیاد.
- الگوی خوب اینه که guardِ authorization رو به authorize()ِ form request ببری تا کنترلر روی مسیر موفق متمرکز بمونه.




