سلامِ 🔥 به دوستان لاراولی! میخوایم هفتمین قسمت از مجموعه پستهای ۸۰ سوال مصاحبه لاراول رو بررسی کنیم که این بار سوالها رو با نکتههای جالبی بررسی میکنیم.
سوالاتی که توی این قسمت بررسی میکنیم:
- چطوری کوئری SQL تو در تو بسازیم؟
- تفاوت متد boot و register توی Provider ها چیه؟
- چه زمانی از Signed URL ها استفاده کنیم؟
- Mix چیه؟
- متد makeVisible الوکوئنت چکار میکنه؟
- متد makeHidden الوکوئنت چکار میکنه؟
- فایل Stub چیه؟
- کاربرد پراپرتی Guarded توی مدل چیه؟
- Auth::once چیه؟
- چطور بررسی کنیم درخواست ajax هست؟
61. چطوری کوئری SQL تو در تو بسازیم؟
کوئری تو در تو یا Nested Query، به کوئریای گفته میشه که داخل پرانتز قرار میگیره. توی این کوئریها، پرانتزها نقش مهمی توی خروجی دارن. پرانتزهای کوئری زیر رو در نظر بگیرید:
SELECT * FROM `users` WHERE (status = 2 OR type = 'admin') AND age > 32
اگه توی Query Builder و توی متد where از کلاژر استفاده کنیم، میشه یک کوئری تو در تو ساخت:
User::where(function($query) { $query->where('status', 2)->orWhere('type', 'admin'); })->where('age', '>', 32) ->get();
با قرار گرفتن یک where درون یک where دیگه، میشه یک کوئری تو در تو ساخت و این کار تا بینهایت عمق میتونه ادامه داشته باشه. برای آشنایی بیشتر پیشنهاد میکنم پست زیر رو بخونین:
62. تفاوت متد boot و register توی Provider ها چیه؟
فریمورک وقتی میخواد اجرا بشه، ابتدا متد register همهی پرووایدرها رو اجرا میکنه. توی این متد نباید از یک پرووایدر دیگه استفاده کنیم. چون ممکنه این پرووایدر هنوز توسط فریمورک پردازش و لود نشده باشه و توی نوبت باشه. واسه همین ممکنه هنوز در دسترس نباشه.
اما به محض اینکه متد register همهی پرووایدرها پردازش شد، متد boot همه پرووایدرها توسط فریمورک شروع به پردازش شدن میکنه. این رو میتونین با یک echo ساده بررسی کنین. پس توی متد boot ما مطمئن هستیم که همهی پرووایدرها رجیستر شدن. پس کارهایی غیر از bind کردن مثل استفاده از یک پرووایدر دیگه، اضافه کردن فایلهای Route، ثبت کردن Event/Listerner ها و ... رو توی متد boot مینویسیم.
63. چه زمانی از Signed URL ها استفاده کنیم؟
یک Signed URL برای اضافه کردن یک لایه امنیتی بیشتر به لینکهایی که بصورت عمومی در دسترس هستن استفاده میشه.
قطعاً توی ایمیلها یک لینک با عنوان «لغو عضویت» یا «Unsubscribe» دیدیم. برای مثال لینک لغو عضویت برای کاربر شماره ۹۰ میتونه به صورت زیر باشه:
http://www.example.com/email/unsubscribe/90
وقتی این کاربر روی این لینک کلیک میکنه دیگه هیچ ایمیلی دریافت نخواهد کرد. حالا تصور کنین یک شخص که به این لینک دسترسی داره، اون رو دستکاری میکنه و بجای ۹۰، از شماره ۸۰ استفاده میکنه. در صورت عضویت ایمیل کاربر شماره ۸۰ هم لغو میشه. و به این صورت میتونه برای بقیه کاربرا هم این عملیات رو انجام بده. از اونجایی که کاربرا برای دریافت خبرنامههای ایمیلی معمولاً لزومی به ثبتنام ندارن، با احراز هویت هم نمیتونیم این قضیه رو کنترل کنیم. اینجاست که Signed URL ها به کار ما میان 👌
برای لینک بالا و کاربر شماره ۹۰، یک Signed URL بصورت زیر هست:
http://example.com/email/unsubscribe/90?signature=3e6aba27c0001198958f6aad59753f2eea24f82230bf24efa892647e04744b30
همونطور که میبینیم یک پارامتر به اسم signature با یک مقدار هش شده به Query String لینک اضافه شده. این مقدار هش شده به صورت اختصاصی برای این لینک تولید شده و با تغییر کردن اون، لینک نامعتبر میشه.
لینک اختصاصی برای کاربر شماره ۸۰ هم بصورت زیر هست. همونطور که میبینیم مقدار هشِ کاملاً متفاوتی داره:
http://example.com/email/unsubscribe/80?signature=43d24243f29ee80eb3a0e445b2de379a91ef83126b1d58ee60b7ae2ce9dd4fd7
پس برای لغو عضویت ایمیل کاربر شماره ۸۰، مقدار signature لینک، باید برابر با مقدار بالا باشه.
64. Mix چیه؟
میکس (Laravel Mix) ابزاری هست که پشت پرده از وبپک (Webpack) استفاده میکنه و برای این معرفی شده تا کار با وبپک رو راحتتر کنه. وبپک که برای کامپایل و مدیریت کردن فایلهای جاوااسکریپت و CSS استفاده میشه، مستندات رسمی اون اونقدر وسیع هست و برای یک توسعهدهنده بکاند که لازم نداره خیلی چیزا رو بدونه، گاهاً گنگ هست. به گفته سازندگان میکس، با استفاده کردن از میکس میتونیم خیلی راحت از ۸۰٪ قدرت وبپک استفاده کنیم.
65. متد makeVisible الوکوئنت چکار میکنه؟
همونطور که میدونیم پراپرتی $hidden توی یک مدل برای مخفی کردن Attribute های مدل هنگام نمایش استفاده میشه:
<?php namespace App\Models; // ... class User extends Authenticatable { protected $hidden = [ 'password', 'remember_token', 'email' ]; }
با توجه به کد بالا، هنگام نمایش یک کاربر، email مخفی خواهد بود. اما توی یک شرایط خاص اگه بخوایم email رو نشون بدیم چطور؟ 🤔 با توجه به اینکه نوع پراپرتی $hidden برابر با protected هست، از بیرون کلاس هم نمیشه اون رو دستکاری کرد. متد makeVisible برای حل این مسئله معرفی شده.
با استفاده از متد makeVisible میتونیم بصورت داینامیک یک Attribute که hidden هست رو نمایش بدیم. از این متد بصورت زیر استفاده میکنیم:
$user = User::find(29); $user->makeVisible(['email']);
وقتی اون آبجکت رو به آرایه تبدیل کنیم، در کنار بقیه Attribute ها، email رو هم خواهیم دید:
dd($user->toArray()); /* [ // ... 'email' => 'email@example.com', // ... ] */
این متد برعکس متد makeVisible هست و برای مخفی کردن یک Attribute بصورت داینامیک استفاده میشه. با استفاده از اون، Attribute ها بطور موقت توی پراپرتی $hidden قرار میگیرن. فرض کنیم توی یک شرایط خاص میخوایم از نمایش دادن email کاربر جلوگیری کنیم. برای این کار از روش زیر استفاده میکنیم:
$user = User::find(29); $user->makeHidden(['email']);
67. فایل Stub چیه؟
وقتی با دستورهای آرتیزان، میخوایم فایلهایی مثل کنترلر، مدل و میدلور بسازیم، فریمورک اونها رو از روی قالبهایی به اسم Stub درست میکنه. هر قالب بصورت یک فایل هست و به عنوان یک اسکلت و یک طرح برای فایلهای واقعی درنظر گرفته میشه. برای مثال، فایل stub برای مدلها شبیه به این هست:
<?php namespace {{ namespace }}; use Illuminate\Database\Eloquent\Model; class {{ class }} extends Model { // }
توی این کد {{ namespace }} و {{ class }} متغیرهایی هستن که موقع ساخته شدن یک مدل از کاربر گرفته میشه.
پیشنهاد میکنم پست زیر رو بخونین:
68. کاربرد پراپرتی Guarded توی مدل چیه؟
بهتره قبلش با پراپرتی $fillable آشنا بشیم. اگه این پراپرتی توی مدل تعریف شده باشه، فقط میتونیم به Attribute هایی مقدار بدیم که توی این پراپرتی تعریف شدن:
<?php namespace App\Models; // ... class User extends Authenticatable { protected $fillable = ['name', 'email']; }
با توجه به کد بالا هنگام ساختن یک کاربر بصورت زیر، فقط name و email میتونن مقدار بگیرن و بقیه موارد نادیده گرفته میشن:
User::create([ 'name' => 'Felix', 'email' => 'email@example.com', 'age' => '...', // ignored 'avatar' => '...', // ignored 'password' => '...' // ignored ]);
حالا میتونیم $guarded رو بهتر بررسی کنیم. اگه این پراپرتی توی مدل قرار بگیره، همه Attribute ها میتونن مقدار بگیرن، بجز اونهایی که توی پراپرتی $guarded قرار گرفتن:
<?php namespace App\Models; // ... class User extends Authenticatable { protected $gaurded = ['password']; }
با توجه به کد بالا، هنگام ساختن یک کاربر، مقداری که به password نسبت میدیم نادیده گرفته میشه:
User::create([ 'password' => '...' // ignored ]);
69. Auth::once چیه؟
هنگام احراز هویت کردن کاربر، در حالت عادی یک سشن درست میشه تا توی درخواستهای بعدی برای مدت زمان مشخصی کاربر احراز هویت شده باقی بمونه. اگه نمیخوایم این سشن درست بشه، از متد once استفاده میکنیم. به این صورت، بعد از پردازش و تموم شدن درخواست، کاربر دیگه احراز هویت شده باقی نمیمونه.
کارایی این متد شبیه attempt هست که باید به آرگومان اولش به صورت آرایه ایمیل و رمز عبور رو پاس بدیم:
$credentials = [ 'email' => $email, 'password' => $password ]; if (Auth::once($credentials)) { // ... }
برای آشنایی بیشتر با احراز هویت لاراول پیشنهاد میکنم پست زیر رو بخونین:
70. چطور بررسی کنیم درخواست ajax هست؟
برای این کار از متد ajax() کلاس Request استفاده میکنیم:
use Illuminate\Http\Request; if (Request::ajax()) { }
اما پشت پرده این متد چی هست؟
public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); }
همونطور که میبینیم، توی درخواست باید یک هدر با عنوان X-Requested-With و مقدار XMLHttpRequest تنظیم شده باشه که مشخص بشه درخواست ایجکس هست که اکثر کتابخونههایی که برای ساختن درخواستهای ایجکس ساخته شدن مثل جیکوئری و Axios، بطور پیشفرض این هدر رو میفرستن.
خب دوستان این هم از قسمت ۷ که امیدوارم براتون مفید بوده باشه. 😉🖐️
منابعی که برای این پست استفاده کردم:
