سلام دوستان! اول تشکر کنم از حمایت‌ها و اظهار لطفتون که باعث میشه با انگیزه بیشتری ادامه بدم 🖐😉

قسمت سوم از مجموعه پست‌های ۸۰ سوال مصاحبه لاراول رو بررسی می‌کنیم. پیشنهاد می‌کنم قبلش مقدمه و قسمت نکته دوستانه رو بخونین.

سوالاتی توی این قسمت بررسی می‌کنیم:

  1. گارد (Guard) چیه؟
  2. چند تا از متدهای پرکاربرد Collection رو نام ببرید
  3. Facade چیه؟
  4. میدل‌ور کد زیر چکار می‌کنه؟
  5. Observer چیه؟
  6. چرا از Form Request استفاده کنیم؟
  7. Localization چیه؟
  8. نسخه‌بندی معنایی چیه؟
  9. چطوری یک متغیر سراسری داشته باشیم؟
  10. توی یک درخواست به دیتابیس چطوری کوئری خام SQL رو ببینیم؟

 

21. گارد (Guard) چیه؟

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

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

با استفاده از متد guard از کلاس Auth می‌تونیم از گارد دلخواه استفاده کنیم:

$user = Auth::user();
$user = Auth::guard('api')->user();
$user = Auth::guard('web')->user();

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

توی فایل config/auth.php می‌تونیم گاردها رو ببینیم و همچنین گاردهای دلخواهمون رو تعریف کنیم.

 

22. چند تا از متدهای پرکاربرد Collection رو نام ببرید

کالکشن (Collection) لاراول بیش از ۲۰۰ تا متد داره که یک توسعه‌دهنده لاراول باید حداقل با ۱۰ تا از اونها آشنایی کامل داشته باشه و شاید از شما پرسیده بشه که مثلاً متد toArray() چکار می‌کنه. از متدهای پرکاربرد کالکشن میشه به toArray - only - except - pluck و همچنین متدهایی که با where شروع میشن مثل whereIn و whereNull اشاره کرد.

برای آشنایی با این متدها می‌تونین رو ببینید.

 

23. فِساد (Facade) چیه؟

همونطور که توی سوال ۲۰ خوندیم، سرویس (کلاس) هایی مثل Cache و Session توی Service Container ثبت شدن. برای دسترسی راحت‌تر به سرویس‌های Service Container از فساد استفاده می‌کنیم. به بیان فنی‌تر، فساد، یک کلاس (رابط) برای دسترسی به این سرویس‌ها بصورت استاتیک هست. برای مثال برای دسترسی به سرویس Cache می‌تونیم از فساد Cache بصورت زیر استفاده می‌کنیم:

use Illuminate\Support\Facades\Cache;

Cache::get('key');

 

24. میدل‌ور کد زیر چکار می‌کنه؟

Route::get('/settings/security', function () {
    // ...
})->middleware(['password.confirm']);

اگه برای دسترسی به یک صفحه، لازمه که کاربر قبلش رمز عبور خودش رو دوباره وارد کنه، می‌تونیم از میدل‌ور password.confirm استفاده کنیم. وقتی برای یک صفحه از این میدل‌ور استفاده می‌کنیم، ابتدا کاربر به صفحه‌ای هدایت میشه که باید رمز عبورش رو وارد کنه و اگه موفقیت آمیز بود، به صفحه‌ی مورد نظرش هدایت میشه.

برای اطلاعات بیشتر از احراز هویت لاراول این پست رو ببینید.

 

25. کلاس Observer چیه؟

واژه Observe یعنی نظاره کردن. توی لاراول Observer به کلاسی گفته میشه که تغییرات مدل رو نظارت می‌کنه و با اتفاق افتادن یک رویداد خاص (مثلاً ساخته شدن، حذف یا ویرایش مدل) کاری که بهش نسبت می‌دیم رو انجام میده.

برای یک مدل الوکوئنت (مثلاً User یا Post) می‌تونه رویدادهای مختلفی رخ بده. مثلاً ساخته‌شدن، ویرایش و یا حذف شدن یک کاربر یا پست. فرض کنیم وقتی یک پست ویرایش میشه، می‌خوایم یک سری عملیات دیگه انجام بدیم. مثلاً کش پست‌ها رو پاک کنیم، تصویر جدید رو با قبلی جایگزین کنیم، تگ‌های نسبت داده شده رو sync کنیم و ... . همه این کارها رو میشه توی کنترلر و توی متد update نوشت. اما با زیادتر شدن عملیاتِ بعد از ویرایش، متد ما شلوغ‌تر و مدیریت اون سخت‌تر و خوانایی اون کمتر میشه.

یک راه بهتر اینه که این عملیات رو به یک کلاس جدا منتقل کنیم. بهترین چیز برای مدیریت رویدادهایی که برای یک مدل اتفاق می‌افته، استفاده از کلاس‌های Observer هست. با این کار، اصل اول SOLID رو هم رعایت می‌کنیم.

 

26. چرا از Form Request استفاده کنیم؟

عملیات اعتبارسنجی (Validation) همیشه ساده نیست و گاهاً نیاز داریم ورودی‌های زیادی رو بررسی کنیم. نوشتن همه کدهای اعتبارسنجی توی کنترلر، باعث شلوغ شدن کنترلر میشه. همچنین انعطاف و امکانات کمتری قبل و بعد از اعتبارسنجی در اختیار داریم. با استفاده از Form Request ها علاوه بر اینکه کدهای منظم‌تر و خواناتری خواهیم داشت، قدرت و اختیار بیشتری روی پردازش ورودی‌ها و نمایش پاسخ به کاربر داریم.

هر Form Request یک کلاس اختصاصی هست که شامل Rule های اعتبارسنجی میشه:

public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

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

public function messages()
{
    return [
        'title.required' => 'لطفاً عنوان را وارد کنید'
    ];
}

همچنین می‌تونیم قبل از شروع اعتبارسنجی، روی ورودی‌ها تغییراتی اعمال کنیم:

protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

با استفاده از Form Request ها، اصل اول SOLID رو هم رعایت می‌کنیم.

 

27. Localization چیه؟

اگه قصد داریم یک برنامه چند زبانه داشته باشیم با ویژگی Localization لاراول می‌تونیم خیلی راحت این کار رو انجام بدیم. کافیه کلمات و جمله‌های هر زبان رو توی پوشه و فایل اختصاصی ذخیره کنیم. پوشه resources/lang    محل نگهداری فایل‌های اختصاصی هر زبان هست.

 

28. نسخه‌بندی معنایی چیه؟

هدف نسخه‌بندی معنایی (Semantic Versioning)، استاندارد سازی شماره‌ی نسخه‌هایی هست که به یک نرم‌افزار نسبت داده میشه. توی نسخه‌بندی معنایی، اعداد یک ورژن، شامل سه عدد هست که با نقطه از هم جدا میشن. یعنی طبق فرمت X.Y.Z که توی اونها x و y و z اعداد صحیح هستن:

X: نشون‌دهنده نسخه اصلی (Major Version) نرم‌افزار هست.
Y: نشون‌دهنده نسخه جزیی (Minor Version) نرم‌افزار هست.
Z: نشون‌دهنده نسخه پچ (Patch) نرم‌افزار هست.

برای مثال برای ورژن 6.12.3 یک نرم‌افزار، نسخه‌ی اصلی 6، نسخه جزیی 12 و نسخه پچ اون 3 هست.

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

 

29. چطوری یک متغیر سراسری داشته باشیم؟

برای داشتن متغیری که همه جای برنامه در دسترس باشه راه‌های زیادی وجود داره که بعضیاشون گاهاً غیر بهینه و غیر استاندارد هستن. مثلاً یک کلاس تعریف کنیم و متغیرها رو بصورت پراپرتی استاتیک تعریف کنیم. یا یک فایل شامل چندین Constant بسازیم و اون رو توی برنامه بصورت دستی include کنیم. اما همونطور که می‌دونیم پوشه config برای حل چنین مسئله‌ای طراحی شده. این پوشه محل نگهداری همه متغیرهای برنامه هست. متغیری که توی این مسیر تعریف بشه توی همه جای برنامه حتی View ها هم براحتی قابل دسترسی هست.

برای این کار ابتدا یک فایل به اسم دلخواه مثلاً settings.php توی پوشه /config درست می‌کنیم با محتویات زیر:

// config/settings.php

<?php

return [
    'api_version' => env('API_VERSION'),
    'path' => [
        'images' => '/assets/images',
        'videos' => '/assets/videos'
    ],
    'theme' => 'dark',
];

و هر جای برنامه با تابع config() از اونها بصورت زیر استفاده می‌کنیم:

config('settings.theme');
config('settings.path.images');
config('settings.path.videos');

 

30. توی یک درخواست به دیتابیس چطوری کوئری خام SQL رو ببینیم؟

یکی از راه‌ها استفاده از متد ->toSql() هست:

$query = \DB::table('users')->where('id', '<>' , 29)->limit(5)->toSql();

dd($query); // "select * from `users` where `id` <> ? limit 5"

استفاده از این متد برای زمانی خوبه که نمی‌خوایم درخواست ما بطور واقعی اجرا بشه و فقط می‌خوایم خروجی خام SQL رو ببینیم.

اگه چندین درخواست متوالی داشته باشیم استفاده از این متد کارساز نیست. برای حل این مسئله از متدهای DB::enableQueryLog() و DB::getQueryLog() استفاده می‌کنیم. متد enableQueryLog رو ابتدای کدی قرار می‌دیم که می‌خوایم کوئری‌های از اون قسمت به بعد رو داشته باشیم. اگه از این متد استفاده بشه، فریم‌ورک توی هر جایی از برنامه که کوئری SQL زده بشه، کوئری خام اونها رو ذخیره می‌کنه. از متد getQueryLog زمانی استفاده می‌کنیم که می‌خوایم گزارش‌هایی که enableQueryLog ذخیره کرده رو ببینیم:

Post::all();

DB::enableQueryLog();

DB::table('users')->get();
$user = User::find(29);
$user->name = 'Ali';
$user->save();

dd(DB::getQueryLog());

توی کد بالا ۳ درخواست بعد از متد enableQueryLog زدیم که خروجی اونها بصورت زیر هست. دقت کنین که درخواست خط اول به حساب نمیاد چون قبل از متد enableQueryLog نوشته شده:

تصویر نوشته

 

خب دوستان امیدوارم این قسمت هم براتون مفید بوده باشه. روزتون خوش. 😉✌️

برای این قسمت از منبع زیر کمک گرفتم: