یادگیری مقدماتی لاراول - پارت دوازدهم

تذکر: این یک پست آموزشی برای عموم نیست! بلکه تنها جایی برای یادداشت‌های من حین یادگیریه تا بهتر به خاطر بسپارم و در صورت لزوم به اون‌ها مراجعه کنم.

قسمت ۱۴۴ تا ۱۵۷


آشنایی با ویژگی‌های جدید لاراول ۸:

لاراول هر ۶ ماه یک ورژن جدید میده، نسخه‌های LTS پشتیبانی ۲ ساله برای رفع باگ و ۳ ساله برای باگ های امنیتی داره، اما نسخه‌های غیر LTS پشتیبانی ۷ ماهه رفع باگ و ۱ ساله امنیتی دارن.

توی لاراول ورژن ۸، ورژن php حتما باید برابر یا بزرگتر از ۷.۳ باشه، برای آپدیت می‌تونیم XAMPP رو آپدیت کنیم و حتما قبلش باید از دیتابیس‌های خودمون بک‌آپ بگیریم.

وقتی composer نصب میشه، متغیرهای محیطی رو ست می‌کنه و به راحتی به php و... داخل CLI دسترسی داریم. پس می‌تونیم به جای پاک کردن XAMPP نسخه جدید php رو نصب کنیم و env جدید رو ست کنیم.


مبحث Model Directory:

توی نسخه‌های قبلی وقتی یک Model ایجاد می‌کردیم؛ می‌رفت و به صورت Name.php داخل پوشهٔ app قرار می‌گرفت؛ اما توی نسخهٔ جدید داخل app/Models قرار می‌گیرن و namespace ما میشه App/Models.

بهبود artisan serve:

قبلا اگر فایل .env رو تغییر می‌دادیم و server ما ران شده بود؛ حتما باید اون رو می‌بستیم و دوباره اجرا کنیم؛ اما توی نسخهٔ جدید به محض تغییر در فایل env، خود سرور restart میشه.


مبحث Routing namespace:

قبلا برای دسترسی به متد یک کنترلر می‌زدیم:

Route::get('/home', 'HomeController@index');

اما حالا باید اینطوری عمل کنیم:

Route::get('/home', [HomeController::class, 'index']);

که فضای نام HomeController رو باید use کنیم:

use App\Http\Controllers\HomeController

از اونجایی که ::class برای ما string اون فضای نام رو برمی‌گردونه، پس می‌تونیم بنویسیم:

Route::get('/home', ['App\Http\Controllers\HomeController', 'index']);

برای resource هم به شکل زیر عمل میشه:

Route::resource('posts', PostController::class);

توی ورژن‌های قبلی لاراول namespace ما use می‌شد؛ اما توی ورژن ۸ این اتفاق نمی‌افته، اما می‌تونیم لاراول رو طوری تنظیم کنیم که این اتفاق بیفته، برای این کار باید مقدار زیر رو در RouteServiceProvider.php از کامنت در بیاریم:

protected $namespace = 'App\\Http\\Controllers';

با این کار به راحتی می‌تونیم به همون روش قدیمی و فرمول زیر به متدهای کنترلر خودمون دسترسی داشته باشیم:

Route::get('/routename', 'NameController@method');

اما بهتره که namespace رو خودمون دستی صدا بزنیم و از اصول لاراول پیروی کنیم.


مبحث Model Factory Class:

همون‌طور که از قبل می‌دونیم؛ factory یک ویژگی‌ هست که کار با seeders رو برای ما راحت‌تر می‌کنه؛ Factoryهای ما توی پوشهٔ database/factories قرار دارن و به فرم زیر هستن:

توی کد بالا، یک متغیر از نوع protected به اسم model داریم که مقدار User::class داره، به همین خاطر به Factory می‌گیم Model Factory.

کلاس فکتوری یک متد داره به اسم definition که توش فیلدهای جدولی که قراره پر بشه رو میاریم و به کمک کتابخونهٔ faker پرش می‌کنیم.

بریم برای ساخت یک Factory واقعی توی لاراول ۸:

php artisan make:factory PostFactory --model=Post

حالا از قبل باید Migration و Model رو داشته باشیم و ستون مد نظر رو توی Migration ایجاد کنیم و migrate بزنیم تا توی دیتابیس اعمال بشه، حالا برای پر کردن ستون می‌تونیم به روش زیر عمل کنیم:

حالا برای صدا زدن Faker می‌تونیم به روش زیر عمل کنیم:

PostFactory::new()->create();

روش دیگه استفاده از مدل Post هست:

Post::factory()->create();

یک متدی داریم به اسم make و تفاوتش با create اینه که دادهٔ فیک ایجاد می‌کنه، اما توی دیتابیس و جدول ذخیره نمی کنه:

Post::factory()->make();

با متد count هم به راحتی می‌تونیم تعداد دیتای فیکی که قراره ایجاد بشه رو مشخص کنیم:

Post:;factory()->count(5)->create();

نمایی از جدول posts:

تغییر بزرگ لاراول Jeststream:

جت استریم در واقع میاد و یک scaffolding سمت فرانت برای ما ایجاد می‌کنه که کلی قابلیت داره، مثل:

۱- لاگین
۲- رجیستر کردن
۳- تایید ایمیل
۴- تایید هویت دو مرحله‌ای
۵- مدیریت سشن‌ها
۶- ساپورت از Laravel Santcum API
و...

جت استریم به صورت دیفالت از فریمورک Tailwind CSS استفاده می‌کنه، اما میشه به جای اون از Livewire و یا Inertia هم استفاده کرد.

در واقع Jetstream که به وسیله Taylor Otwell نوشته شده، کمک می‌کنه که بخش‌های مختلف فرانت پروژه رو خیلی سریع با کمک Tailwind CSS و Livewire و Inertia توسعه بدیم. اما طبیعتا اجباری در استفاده از اون نیست و ما همچنان می‌تونیم از بسته Laravel/ui برای توسعه فرانت کمک بگیریم.

این بسته در بک‌اند از پکیج Fortify برای پیاده‌سازی auth و... کمک می‌گیره که این خیلی مهمه و ما می‌تونیم از این بسته با فرانت دلخهواه خودمون مثل ‌Bootstrap استفاده کنیم.


آشنایی مقدماتی با فریمورک Tailwind:

یک فریمورک برای CSS (مثل bootstarp و materialize) که به راحتی قابل کاستوم کردنه، علت اینکه خیلی راحت میشه یک طرح کاستوم باهاش زد، اینه که این یک فریمورک سطح پایین هست و چیزهایی مثل کامپوننت‌های آمادهٔ بوت استرپ رو اینجا نمی‌بینیم؛ مثلا دیگه کلاسی برای ایجاد card وجود نداره و این برنامه نویس هست که باید با کنار هم قرار دادن کلاس‌های مختلف (به صورت ماژولار)، اون چیزی که دنبالش هست رو ایجاد کنه.


آشنایی مقدماتی با Livewire:

خب livewire یک فریمورک فول استک برای لاراوله، این فریمورک فقط و فقط روی لاراول کار می‌کنه و هدفش ایجاد یک اینترفیس داینامیک برای ما هست تا بدون refresh شدن صفحه، اکشن‌های خاصی رو انجام بده (ارتباط با سرور بدون نیاز به رفرش کردن صفحه).

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

آیا با اومدن چیزی مثل Livewire باید فریمورک‌های فرانت مثل Vue و React رو بذاریم کنار؟
خیر، چرا که با توجه به هدف پروژه ما میاییم و ابزار رو انتخاب می‌کنیم؛ مثلا اگر قرار باشه فرانت پروژه کاملا از بک پروژه جدا باشه، بک پروژه ممکنه روی یک سرور باشه و فرانت روی یک سرور دیگه و... پس مجبوریم از فریمورک‌های فرانتی استفاده کنیم.

اما livewire توی پروژه‌های کوچکتر کاربرد داره و Front و Back هر دو لاراولی هستن، اما این مزیت بزرگ رو ایجاد می‌کنه که بدون نیاز به دانش عمیق فرانت، اپلیکیشن‌های خوبی رو پیاده‌سازی کرد.


آشنایی مقدماتی با Inertia:

با استفاده از Inertiajs میشه یک single page application ایجاد کرد؛ در واقع این Inertia به ما کمک می‌کنه که Dynamic Interface ایجاد کنیم؛ بدون اینکه نیازی به API داشته باشیم. Inertia برخلاف Livewire که اصلا از فریمورک‌های فرانتی استفاده نمی‌کنه، از فریمورک‌های فرانتی استفاده می‌کنه، با این تفاوت که API دیگه وجود نداره.


آشنایی با بستهٔ Fortify:

بستهٔ Fortify لاراول یک Back-end برای سیستم Authentication هست که مستقل از frontend عمل می‌کنه. قبلا برای سیستم auth از laravel/ui استفاده میشد که مشکل اصلی اون این بود که فقط از bootstrap، React و Vue پشتیبانی می‌کرد و برای سایر فریمورک‌های باید یه سری customization انجام می‌دادیم؛ اما توی Fortify دیگه وابسته به فرانت نیستیم و این سیستم مستقل از فرانت در بک پیاده‌سازی میشه.

توی Fortify کافیه که input های خودمون رو به روت‌های Fortify ارسال کنیم تا خودش باقی کارها رو انجام بده. ما یه سری داده رو ارسال می‌کنیم به روتی که نیاز داریم و بقیه کارها در سمت بک به وسیله این بسته هندل میشه.

برای نصب این بسته:

composer require laravel/fortify

بعد هم باید منابع Fortify رو publish کنیم:

php artisan vendor:publish --provider=&quotLaravel\Fortify\FortifyServiceProvider&quot

با دستور بالا، Service Provider این بسته رو از vendor به پوشهٔ Providers پابلیش کردیم. و در نهایت باید یک بار migrate بزنیم تا ستون‌های مورد نیاز Fortify در جدول users اضافه بشه.

php artisan migrate

یکی از این ستون‌ها، two-factor_secret هست و دیگری two_factor_recovery_codes.

نکته بعدی اینکه حتما باید FortifyServiceProvider رو به فایل app.php در config اضافه کنیم:

'providers' => [ App\Providers\FortifyServiceProvider::class, ...];


با نصب Fortify و اضافه کردن Service Provider اون به پروژه و عملیات migrate و تنظیم app.php حالا باید بریم ببینیم که چه بلایی بر سر پروژه اومده و چه چیزهایی اضافه شده:
توی پوشهٔ app یک پوشه به اسم Actions به وجود اومده که داخل اون یک پوشه به اسم Fortify هست که یک سری از کلاس‌های این بسته درش قرار دارن:

فایل FortifyServiceProvider.php هم که دو تا متد boot و register داره:

توی همین متد boot می‌تونیم view لاگین، رجیستر و... رو تعیین کنیم.

فایل مهم بعدی مربوط به کانفیگ‌های Fortify میشه که توی پوشهٔ config با نام fortify.php قرار گرفته. این کانفیگ شامل مواردی مثل لاگین با username یا email، تغییر فیلد email، فعال و غیرفعال‌سازی featureها و... میشه.

خب، حالا بریم سراغ اینکه view مربوط به صفحهٔ لاگین رو تعریف کنیم و توی متد boot مربوط به FortifyServiceProvider اون view رو فراخوانی کنیم:

خب یه فایل login.blade.php هم باید توی resources ایجاد کنیم و یه المنت فرضی توش بذاریم. نکتهٔ مهم بعدی هم اینه که برخلاف laravel/ui در fortify نیازی به پیاده‌سازی route برای صفحهٔ authentication نداریم. حالا با رفتن به localhost:8000/login وارد صفحهٔ لاگین می‌شیم.

برای رجیستر هم می‌تونیم همین کار رو بکنیم:

توی laravel/ui بسته‌های مورد نیاز به package.json اضافه میشدن و به راحتی می‌تونستیم نصبشون کنیم؛ اما توی بحث fortify باید این کار رو (یعنی نصب بوت استرپ) رو دستی انجام بدیم:

نکته: اون خط‌های قرمز که نشون دهندهٔ خطا هست؛ مشکلی نداره و توی فیلم آموزشی بعد از اینکه vscode رو ری استارت کرد؛ حل شد، ظاهرا توی شناختن namespace مربوط به fortify مشکل داشت که حل شد.


برقراری ارتباط بین فرانت و Fortify:

برای استفاده از Bootstrap داخل پروژهٔ لاراولی خودمون چندین راه داریم:
۱- نصب از طریق npm
۲- استفاده از CDN
۳- دانلود فایل‌ها و استفاده از اون داخل public (دسترسی با asset helper function)


در واقع قبلا که با laravel/ui کار می‌کردیم؛ این بسته می‌اومد و با npm که یک پکیج منجر هست سه تا کتابخونهٔ Vue.js یا react و یا bootstrap رو برای ما نصب می‌کرد؛ در واقع بسته‌های مورد نیاز به package.json اضافه میشد؛ بعد ما نصبش می‌کردیم و با laravel mix ازش خروجی می‌گرفتیم.

روش حرفه ای تر نسبت به CDN و استفاده از فایل‌های دانلودی در public، استفاده از package manager هست. یعنی با npm هر چیزی رو که نیاز داریم نصب کنیم و با laravel mix در نهایت compile کنیم و بزنیم تنگ پروژه. برای این کار یک پوشه به اسم css و js در public می‌سازیم و با mix خروجی نهایی رو اونجا قرار می‌دیم.

برای نصب بوت استرپ و ملزوماتش با npm اول از همه یک npm install می‌زنیم تا بسته‌های زیر نصب بشه:

بعدش نیازمندی‌های بوت استرپ رو نصب می‌کنیم:

npm install bootstrap popper.js sass jquery sass-loader

بسته sass-loader برای webpack هست که میاد و sass رو برای ما compile می‌کنه. تمامی این بسته‌ها توی پوشهٔ node_modules توی root پروژه نصب میشن.

خب حالا باید با laravel mix بیاییم و فایل‌های css و js رو کامپایل کنیم و توی js و css داخل public قرار بدیم؛ در واقع خود laravel mix میاد و از webpack برای این کار استفاده می‌کنه.

توی تصویر بالا داریم فایل app.js رو داخل پوشهٔ resources/js می‌بینیم که اومده و فایل bootstrap رو require کرده اما باید توجه داشته باشیم که این بوت استرپ راه‌انداز ما هست و نه اون فریمورک css. اگر نگاهی به فایل bootstrap.js که در واقع راه‌انداز ما هست بندازیم می‌بینیم که میاد و یه سری ابزار و بسته رو require می‌کنه، در نهایت laravel mix با استفاده از webpack میاد و این بسته‌ها رو commpile و تبدیل به یک فایل واحد می‌کنه و داخل public/js قرار میده:

برای اینکه بتونیم bootstrap و jquery و popper.js رو هم کامپایل کنیم؛ باید خطوط زیر رو به راه انداز اضافه کنیم:

وقتی متغیر رو به صورت window.name تعریف می‌کنیم در واقع اون name به صورت global در دسترس هست.

نکته: توی تصویر بالا که اومده مثلا popper.js یا jquery رو require کرده فقط و فقط اسم بسته رو آورده که منظورش اینه که از node_modules بخون، اما توی app.js که راه‌انداز رو require کرده دقیقا گفته که ./bootstrap یعنی توی پوشهٔ جاری فایل bootstrap که البته میشد ./bootstrap.js هم نوشت.

برای کامپایل شدن فایل‌های sass مربوط به بوت استرپ هم باید داخل resources/sass فایل app.scss رو ایجاد کنیم و داخلش عبارت زیر رو قرار بدیم تا بیاد و فایل scss مربوط به بوت استرپ رو از node_modules لود کنه:

حالا باید فایل‌های موجود در node_modules رو که توی resources فراخوانی شدن، با استفاده از لاراول میکس و webpack کامپایل کنیم تا به صورت یک فایل جاوااسکریپتی یا css یکتا در بیان و خیلی راحت وابستگی هاشون هندل بشه و توی پروژه لود بشن.


در زیر تصویری از webpack.mix.js رو می‌بینیم که توش laravel-mix رو require کردیم؛ بعدش هم با استفاده از متدهای js و sass اومدیم و گفتیم که فایل‌های موجود در app.js و app.scss رو برای ما توی public کامپایل کنه:

برای کامپایل کردن، میزنیم:

npm run dev

بعد از کامپایل این رو می‌بینیم:

حالا خیلی راحت توی فایل‌های blade اون‌ها رو صدا می‌زنیم:

طراحی صفحات Login و Register و ایجاد ارتباط میان input‌ها با Fortify:

برای هندل کردن لاگین با Fortify باید داخل FortifyServiceProvider با استفاده از متد loginView بیاییم و view مربوط به لاگین رو صدا بزنیم:

برای رجیستر، reset password و ...:

محتوای فایل‌های blade مربوط به سیستم fortify auth رو اینجا آپلود کردم که البته در دسترس عموم نیست! ولی با ثبت نام توی webprog می‌تونید دانلودش کنید.

تغییر سیستم لاگین از email به username:

برای این کار باید یک فیلد username به migration جدول users اضافه کنیم و اون رو از نوع unique ست کنیم:

و باید:

// drop all tables and then run migration
php artisan migrate:fresh

حالا باید یک input برای user به blade فایل اضافه کنیم؛ بنابراین توی register.blade.php باید این فیلد رو به شکل زیر اضافه کنیم:

خب view ما به شکل زیر در میاد:

حالا باید کدهای مربوط به validation و ثبت user رو به CreateNewUser توی app/Actions/Fortify اضافه کنیم. در زیر کدهای validation مربوط به username رو می‌بینیم که بهش گفتیم unique:users یعنی داخل جدول users یکتا و واحد باشه.

ثبت شدن رو باید به متد create هم اضافه کنیم:

و حتما باید username رو به متغیر fillable داخل مدل User هم اضافه کنیم:

باید view مربوط به login.balde.php رو هم برای پذیرش username اوکی کنیم:

و view زیر رو تحویل می‌گیریم:


حالا باید به Fortify هم بگیم که به جای email با username لاگین کنه، پس باید config/fortify.php رو اینطوری تنظیم کنیم:

ایمن‌سازی رمز عبور:

باید وارد app/Actions/Fortify/PasswordValidationRules بشیم و اونجا ruleهای جدید رو وارد کنیم. ما با اضافه کردن قطعه کد زیر، به لاراول گفتیم که برای password حتما باید ترکیبی از رشته و اعداد باشه:

(new Password)->requireNumeric()


برای اینکه حروف بزرگ، کوچک و کاراکترهای خاص رو هم شامل بشه: