اضافه کردن قابلیت تم بندی به لاراول

سلام. یادم میاد چند وقت پیش که با پکیج ماژولار (صفحه گیت‌هاب ماژول بندی لاراول) لاراول آشنا شدم انگار همه اون چیزی که لاراول کم بود رو یکجا پیدا کرده بودم. خیلی خوب بود که میتونستم برنامم رو کپسوله کنم و هر بخشی رو کامل از بخش دیگه جدا کنم. این روند ادامه داشت تا کم‌کم کمبود یا نبود قابلیت تم بندی توی برنامم دیگه داشت اذیت میکرد. شروع کردم به گشتن. یکم گشتم ولی اون چیزی که دوست داشتم پیدا نشد. (https://github.com/FaCuZ/laravel-theme): این بهترین پروژه اوپن سورسی بود که پیدا کردم ولی بازم به دلم نشست چون باید همه کنترلرهامو تغییر میدادم و این خارج از صبر و حوصله من بود.بلاخره نشستم به خوندن سورس لاراول اون چیزی که میخواستم رو پیدا کردم. توی کلاس ‌Application بود!!!ولی قبل از این که کلاس Application رو تغییر بدیم نیاز داریم که یک سری پیش نیاز رو درست کنیم که اول به اونا می‌پردازیم و بعدش میریم سراغ Application.ساخت فایل themes.jsonیک فایل به نام themes.json درون پوشه resources درست می‌کنیم. دلیل این که این فایل رو با پسوند json درست کردیم اینه که بعدا هم توی php ازش استفاده میکنیم هم توی webpack! فایل themes.json دارای دو متغیر اصلیه، یکی active که اسم تم فعال برنامه رو درون خودش نگه‌داری می‌کنه، یکی دیگه هم list که برامون لیستی از تم‌های موجود توی برنامه رو نگه‌داری میکنه که بعدا اگر خواستم بتونیم به لیست تم‌های موجود دسترسی پیداکنیم. (لیست برای من بیشتر یک جنبه تکمیلی داره و شما میتونین حذفش کنین!)نمونه فایل themes.json انتقال resourceها به درون پوشه تمخب از اونجایی که میخوایم برنامه رو تم بندی کنیم، بهتره همه فایل هایی که تم ها استفاده میکنن رو از هم جدا کنیم که این فایل شامل هر فایلی که داخل پوشه resource هست می‌شه. خب از اونجایی که تمام فایل‌های درون پوشه resource در حال حاضر مربوط به یک تم می‌شه رو به داخل اسم همون تم درون پوشه تم انتقال میدیم. (اینجا تمی که من استفاده میکنم اسمش metronicه و واسه همین از این به بعد از این اسم واسه پوشه تمم استفاده می‌کنم.) ساختار پوشه resources بعد از انتقال فایل ها به پوشه مربوط به تمخب پس اگر تا اینجای کار درست پیش رفته باشیم درون پوشه resource ما یک فایل themes.json وجود داره و چند تا پوشه به نام تم‌های برنامه.فایل های webpack.mix.js و package.jsonخب ما میدونیم که هر تمی یک سری فایل js و css مربوط به خودش رو داره و ما برای این که بتونیم تا حد امکان برنامه رو منعطف نگه داریم و برای تغییر تم به کمترین تغییرات توی برنامه نیاز داشته باشیم فایل های webpack.mix.js و package.json رو درون پوشه هر تم درست میکنیم.درون فایل webpack.mix.js تمام محتوای webpack قدیمی که درون پوشه اصلی برنامه قرار داشت رو قرار میدیم و به شکل زیر تغییر میدیمش.قالب اصلی webpack.mix هر تمکه برای من به صورت زیر شد.فایلی که من درون webpack.mix خودم استفاده می‌کنم! و برای فایل package.json همه پیش نیاز های برنامه رو قرار میدیم.(چون ما قبلا کلا یک تم داشتیم میتونیم فایل رو به صورت مستقیم از پوشه اصلی برنامه درون پوشه تم مورد نظرمون کپی می‌کنیم.)نیاز به بهبود: از اونجایی که من تجربه زیادی توی nodjs و webpack ندارم ممکنه برای تغییراتم راه بهتری هم باشه و برای package.json راهی پیدا نکردم که npm نیازمند‌ی‌های پروژه رو به صورت خودکار از داخل package.json خود تم بخونه و نصب کنه و وقتی میخوایم تم رو عوض کنیم باید package.json رو از داخل پوشه تم به پوشه اصلی کپی کنیم که بتونیم نیازمندی‌هاشو نصب کنیم! ( از دوستان کسی اگر تجربه ای توی این زمینه داره ممنون میشم راهنمایی کنه تا این مطلب تکمیل تر بشه.)فایل webpack.mix.js اصلیاز اونجایی که فایل webpack نیاز داره از درون پوشه خود تم اجرا بشه ما یک فایل webpack.mix.js درون پوشه اصلی پروژه درست میکنیم (همون فایل اصلی که موقع نصب لاراول بین فایل ها وجود داره) و به صورت زیر تغییرش می‌دیم.تغییر فایل webpack اصلی برای اجرا فایل webpack تم.از الان به بعد هر موقع دستورهای npm run ... رو اجرا کنیم فایل webpack مخصوص به تم اجرا میشه و ما نیازی به تغییر webpack نداریم.خب تقریبا تمام کارهایی که پیش نیاز بود رو انجام دادیم. تا الان ما فایل های css و js برنامه جدا شدن و به صورت خودکار از داخل پوشه تم خونده و اجرا میشن، فقط میمونه فراخوانی view ها که زمانی که ما یک view رو فراخوانی میکنیم، برنامه به صورت خودکار از تم مورد نظر بخونه و اجرا کنه!شروع از فایل index.phppublic/index.phpخوب از اونجایی که برنامه ما همیشه از داخل پوشه public و فایل index.php اجرا میشه، در اولین مرحله فایل autoload کومپوزر بارگذاری میشه که وظیفه لود کردن کلاس ها و فایل ها رو به عهده میگیره! بعد از اون میاد فایل app.php از داخل پوشه bootstrap رو بارگذاری میکنه که از این فایل به ما یک شی از کلاس Illuminate\Foundation\Application برگشت داده میشه. بعدش ما یک شی از درخواست کاربر تحت کلاس Illuminate\Http\Request درست میکنیم و به کرنل ارسال میکنیم که برامون پردازشش کنه و جواب متناسب رو برگرودنه. بعدش درخواست رو به کاربر بر می‌گردونیم و تموم، کاربرمون جوابشو گرفته. دستکاری کلاس Illuminate\Foundation\Applicationخوب از اونجایی که کلاس Illuminate\Foundation\Application داخل فایل bootstrap/app.php ساخته میشه، میریم یک سری به اونجا میزنیم و یک سری تغییراتی که میخوایم بدیم رو اونجا اعمال میکنیم!فایل bootstrap/app.phpخب همینطور که می‌بینیم توی این فایل یک شی از کلاس Application می‌سازه ادرس پوشه جاری رو به عنوان آدرس اصلی اجرایی برنامه ارسال میکنه (البته اگر داخل $_ENV متغیر APP_BASE_PATH تنظیم نشده باشه!).ما نیاز داریم که این که کلاس رو مطابق نیازمون یک‌سری تغییرات ریز بدیم که در ادامه با هم اون تغییرات رو اعمال میکنیم تا برنامه به صورت پویا تم رو فراخونی کنه.ساخت کلاس Application داخل پوشه Appخب از اونجایی که ما نمیتونیم داخل پوشه vendor تغییرات ایجاد کنیم و اگر تغییری ایجاد کنیم با هر بار نصب یا اپیدت composer همه تغییرات به فنا میره، یک کلاس به اسم Application داخل پوشه app درست میکنیم و اونو از کلاس Illuminate\Foundation\Application ، Extend میکنیم و تغییرات زیر رو درونش میدیم. فایل Application تغییر داده شده اگر یک زمانی به فایل نیاز داشتین میتونین اینجا به این فایل دسترسی داشته باشین.خب دیگه تقریبا تغییرات تمومه و فقط میمونه فایل bootstrap/app.php که به صورت زیر تغییرش میدیم.فایل bootstrap/app.phpخب دیگه تغییراتمون تموم شد و از الان به بعد به راحتی میتونیم از تم بندی سایتمون لذت ببریم.راستی شما داخل کنترلرهاتون هیچ تغییری نیاز ندارین بدین چون داخل هسته لاراول پوشه تم مورد نظرتون رو به عنوان پوشه resource معرفی کردین و فقط کافیه مثل قدیم از تابع view() استفاده کنین تا فایل های viewتون رو فراخونی کنین.از الان به بعد موقع تعویض تم شما فقط نیاز دارین کهاسم تم فعال داخل فایل themes.json رو تغییر بدین.فایل package.json نیازمندی های پروژه رو کپی کنین.نیازمندی های پروژه رو نصب کنید.فایل های css و js تم رو خروجی بگیرید.