نکته و ترفند برای مدیریت موثر تاریخ و زمان در لاراول

در زمان گم نشوپکیج کربن کمک می‌کنه تا به صورت بهینه‌تری تاریخ و زمان رو در PHP و لاراول مدیریت کنیم اما اکثر اوقات پروژه نیازمندی‌هایی داره که ناخودآگاه کد مارو به سمت پیچیدگی میبره و اینجاست که باید هنر به خرج بدیم و کاری کنیم تا تمیزی رو در کدهای خودمون نگه‌داریم.یکی از کارهای رایج موقع کار با تاریخ و زمان فیلتر کردن اونا به کمک Eloquent هست که اگه مراقب نباشیم به راحتی میتونیم کد کثیفی تولید کنیم. در این مقاله بررسی می‌کنیم که چطور با ایجاد یک trait بتونیم به صورت موثر تاریخ و زمان رو مدیریت کنیم.قدم اول: ساخت traitپوشه جدیدی با نام Traits در پوشه app بسازید و فایلی با نام HasManageableDate.php در اون پوشه ایجاد کنید و در ادامه namespace براش مشخص کنید:namespace App\Traits;و از اونجایی که قراره به کمک کربن تاریخ و زمان رو مدیریت کنیم پس باید فراخوانیش کنیم:use Illuminate\Support\Carbon;چون قراره جنس پارامترهای ورودی و خروجی رو خودمون تعیین کنیم پس لازمه که کلاس Builder رو فراخوانی کنیم چون یک شی از این کلاس قراره بهمون کمک کنه با eloquent تعامل کنیم.use Illuminate\Database\Eloquent\Builder;و نهایتا لازمه که قالب trait خودمون که اسمش HasManageableDate هست رو ایجاد کنیم:trait HasManageableDate {}تا اینجا فایل HasManageableDate.php به این صورت میشه:<?php namespace App\Traits; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Carbon; trait HasManageableDate {}قدم دوم: ایجاد ساختار traitدر این مرحله باید از مفهوم scopeها در لاراول استفاده کنیم تا بتونیم متدهایی رو تولید کنیم که بتونند در همه قسمت‌های اپلیکیشن با Eloquent کار کنند. اولین متد رو با نام scopeToday ایجاد کنید و این متد قراره رکوردهایی که امروز در جدول مورد نظر دیتابیس ما تولید شدند رو به ما برگردونه.public function scopeToday(Builder $query, string $column = 'created_at'): void { $query->whereDate($column, today()); }تو متد بعدی قراره تمامی رکورد‌هایی که دیروز از جدول مورد نظر دیتابیس ما تولید شدند رو بگیریم و برای همین اسمش scopeYesterday هست.public function scopeYesterday(Builder $query, string $column = 'created_at'): void { $query->whereDate($column, Carbon::yesterday()); }متد بعدی اسمش scopeCurrentWeek هست و قراره تمامی رکوردهایی از جدول مورد نظر دیتابیس رو برگردونه که از روز اول هفته فعلی تا روزی که در اون هستیم ایجاد شدند.public function scopeCurrentWeek(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfWeek(), now()]); }متد بعدی که اسمش scopeCurrentMonth هست، قراره تمامی رکوردهایی از جدول مورد نظر دیتابیس رو برگردونه که از روز اول ماه فعلی تا روزی که در اون هستیم ایجاد شدند.public function scopeCurrentMonth(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfMonth(), now()]); }متد بعدی scopeCurrentQuarter هست که تمامی رکوردهایی از جدول مورد نظر دیتابیس رو برمیگردونه که از روز اول ماه فصل فعلی تا روزی که در اون هستیم ایجاد شدند.public function scopeCurrentQurter(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfQuarter(), now()]); }متدscopeCurrentYear هم تمامی رکوردهایی که از جدول مورد نظر دیتابیس از روز اول سال فعلی تا روزی که در اون هستیم ایجاد شدند رو برمیگردونه.public function scopeCurrentYear(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfYear(), now()]); }متد بعدی قراره تمامی رکوردهایی از جدول مورد نظر دیتابیس که در 7 روز گذشته (با احتساب امروز) ایجاد شدند رو برگردونه و برای همین اسمش scopeLast7Days هست.public function scopeLast7Days(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [today()->subDays(6), now()]); }متد بعدی تمامی رکوردهایی از جدول مورد نظر دیتابیس که در 30 روز گذشته (با احتساب امروز) ایجاد شدند رو برگردونه و برای همین اسمش scopeLast30Days هست.public function scopeLast30Days(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [today()->subDays(29), now()]); }به کمک متد بعدی تمامی رکوردهایی از جدول مورد نظر دیتابیس که در 90 روز گذشته (با احتساب امروز) ایجاد شدند رو میگیریم و برای همین اسمش scopeLast90Days هست.public function scopeLast90Days(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [Carbon::today()->subDays(89), Carbon::now()]); }متد بعدی قراره scopePreviousWeek باشه که تمامی رکوردهایی از جدول مورد نظر دیتابیس که هفته گذشته ایجاد شدند رو برای ما میگیره.public function scopePreviousWeek(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfWeek()->subDays(7), now()->startOfWeek()]); }متد بعدی هم scopePreviousMonthهست که تمامی رکوردهایی از جدول مورد نظر دیتابیس که ماه گذشته ایجاد شدند رو برای ما میگیره.public function scopePreviousMonth(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfMonth()->subMonth(), now()->startOfMonth()]); }و متد بعدی هم scopePreviousQuarterهست که تمامی رکوردهایی از جدول مورد نظر دیتابیس که فصل گذشته ایجاد شدند رو برای ما میگیره.public function scopePreviousQuarter(Builder $query, string $column = 'created_at'): void { $query->whereBetween($column, [now()->startOfQuarter()->subMonths(3), now()->startOfQuarter()]); }طبق مفهوم accessor در لاراول قراره که تفاوت زمانی تاریخی که یک رکورد ایجاد شد با زمان حال حاضر رو بگیریم و نشون بدیم پس برای همین اسم متد بعدی createdTimeDiff هست.public function createdTimeDiff(): Attribute { return Attribute::make( get: fn () => $this->created_at->diffForHumans(), ); }در متد بعدی قصد داریم تفاوت آخرین زمانی که رکورد موردنظر ما آپدیت شد رو با زمان حال حاضر بگیریم و برای همین اسمش رو lastUpdatedTimeDiff قرار میدیم.public function lastUpdatedTimeDiff(): Attribute { return Attribute::make( get: fn () => $this->created_at->diffForHumans(), ); }چطور ازش استفاده کنیم؟لازمه این trait رو رو در Model موردنظر خودتون فراخوانی کنید تا بتونید ازش استفاده کنید:<?php namespace App\Models; use App\Traits\HasManageableDate; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Product extends Model { use HasFactory, HasManageableDate; // ... }حالا هر متدی که در trait تعریف شده میشه استفاده کرد تا رکوردهای موجود در جدول مربوطه رو فیلتر کنیم.$todayProducts = Product::today()->get();و برای گرفتن نمایش فاصله زمانی کاربرپسند الان نسبت به زمانی که یک رکورد ایجاد شد به روش پایین عمل میکنیم:$user = User::find(1); $userCreatedAt = $user->created_time_diff;فایل نهایی HasManageableDate.php برای کمک به مدیریت بهینه‌تر تاریخ و زمان رو در گیت‌هاب قراردادم و مطمئنم که میتونه تو پروژه‌ها مفید باشه.نتیجه‌گیریتو این مقاله برای کار با تاریخ و زمان از کربن استفاده کردیم و برای جلوگیری از تکرار کدها یک trait ایجاد کردیم. شما میتونید براساس نیاز خودتون این trait رو تغییر بدید، مثلا در متدها تغییراتی ایجاد کنید، متد جدیدی اضافه کنید یا متد موجود رو حذف کنید تا مناسب پروژه شما باشه. امیدوارم که این مقاله برای شما مفید بوده باشد و لطفا اگر سوال یا نظری دارید حتما بهم بگید و در آخر ممنونم بابت وقتی که گذاشتید.