توسعه دهنده سمت سرور (پیاچپی و لاراول)
مدیریت تاریخ و زمان در لاراول توسط کربن
برای کار با تاریخ و زمان در PHP و لاراول میتونیم از توابع و کلاسهای PHP استفاده کنیم ولی همونطور که میدونید این روش پیچیدگیهایی داره و برای همین بسیاری از توسعهدهندهها از پکیج دیگهای به اسم Carbon استفاده میکنند.
پکیج کربن در واقع یک افزونه برای DateTime
در PHP هست که در پسزمینه از کلاس DateTime
ارثبری میکنه. به کمک این پکیج کدهای سادهتر و بامعنیتر تولید میشه و همچنین خوانایی و قابلیت نگهداری برای تاریخ و زمان به پروژه اضافه میشه.
فریمورک لاراول بهطور پیشفرض از Carbon استفاده میکنه ولی در مستندات چیز زیادی دربارش نگفته پس لازمه که خودمون وارد عمل بشیم و بفهمیم که چطور باید تاریخ و زمان رو در لاراول به کمک Carbon مدیریت کنیم.
کربن چه کارهایی رو انجام میده؟
به طور خلاصه تعامل با تاریخ، زمان و timezone(منطقه زمانی) به کمک کربن راحتتر میشه، یعنی:
- ساخت datetime
- تبدیل datetime بین timezoneهای مختلف
- ایجاد تغییرات در datetime(اضافه و کم کردن)
- محاسبه اختلاف بین دو فاصله زمانی
- تبدیل datetime به متن مناسب و قابل فهم برای انسانها
لطفا تکه کد پایین رو ببینید تا متوجه پتانسیل کربن در ایجاد سادگی، زیبایی و خوانایی در پروژه بشید:
$trialExpires = now()->addDays(30);
فراخوانی و خواندن تاریخ
اگه از لاراول استفاده میکنید اصلا نیاز نیست کربن رو نصب کنید چون همونطور که گفتیم به صورت پیشفرض به همراه لاراول نصب میشه و در اختیار توسعهدهندهها قرار میگیره و کافیه برای فراخوانی Carbon به روش زیر عمل کنیم:
use Illuminate\Support\Carbon;
طبق این Pull Reqest کد بالا اصل پکیج Carbon رو در یک نگهدارندهای میپیچه که باعث میشه قابلیت macroable بودن به carbon در لاراول اضافه بشه. البته هنوز هم میتونید از پکیج کربن به صورت مستقیم استفاده کنید:
use Carbon\Carbon;
هرجا که نیاز داشته باشیم میتونیم ازش نمونهسازی کنیم:
$current = new Carbon();
$newYear = new Carbon('first day of January 2024');
توابع کمکی ()now
و ()today
در لاراول از کربن استفاده میکنند و البته میتونیم به صورت مستقیم یه سری از متدهای محبوب کربن رو به صورت استاتیک صدا بزنیم:
$yesterday = Carbon::yesterday();
$today = Carbon::today();
$current = Carbon::now();
$londonCurrentTime= Carbon::now('Europe/London');
$tomorrow = Carbon::tomorrow();
میتونیم برای متدهای بالا timezone تعیین کنیم ولی اگر اینکار رو نکنیم timezone پیشفرض UTC+0 در نظر گرفته میشه و اگه بخوایم براساس آرگومانهای ورودی تاریخ و زمان ایجاد کنیم متدهای استاتیک مخصوص این کار وجود دارند:
Carbon::createFromDate($year, $month, $day, $tz); // ساخت تاریخ
Carbon::createMidnightDate($year, $month, $day, $tz); // ساخت تاریخ بر اساس زمان 00:00
Carbon::createFromTime($hour, $minute, $second, $tz); // ساخت زمان
Carbon::createFromTimeString("$hour:$minute:$second", $tz); // ساخت زمان براساس رشته
Carbon::create($year, $month, $day, $hour, $minute, $second, $tz); // ساخت تاریخ و زمان
میتونیم آرگومانهای بالا رو null
ارسال کنیم و Carbon مشخصات زمانی همین الان رو برای اون آرگومان در نظر میگیره.
به کمک استاتیک متد parse به صورت مستقیم زمانی رو برای کربن تعریف کنیم تا براساس اون یک شی Carbon بسازیم:
$lastDayOfFeb2021 = Carbon::parse('last day of February 2021');
یا حتی به کمک این متد میتونیم براساس timestamp ورودی یک شی Carbon درست کنیم:
$lastDayOfFeb2021 = $Carbon::parse(1614470400);
تغییر تاریخ
دریافت تاریخ تنها کاری نیست که میتونیم با پکیج کربن انجام بدیم، بلکه میتونیم با استفاده از این پکیج تاریخ مورد نظر رو تغییر هم بدیم.
now()->addDays(3);
now()->subDays(3);
حتما به این بخش از مستندات کربن برای دیدن لیست کامل متدهایی که برای تغییر تاریخ بهشون نیاز داریم سر بزنید.
استفاده از Getters و Setters
وقتی از پکیج carbon استفاده میکنیم دست ما به عنوان توسعهدهنده باز هست، یعنی میتونیم از هر روشی که برامون خوشایند هست استفاده کنیم تا خواسته رو برآورده کنیم. مثلا در کنار روشهای بالا میتونیم برای خواندن و تغییر تاریخ از Getterها و Setterها استفاده کنیم.
$datetime = Carbon::now();
$datetime->year = 2024;
echo $datetime->year;
اگه روش بالا رو دوست ندارید هیچ اشکالی نداره، یه نگاه به روش پایین بندازید:
$datetime = Carbon::now();
$datetime ->year(2024);
echo $datetime ->year();
حتی میتونیم از این متدها به صورت زنجیری استفاده کنیم:
$dt= Carbon::now();
$dt->year(2024)->month(1)->day(7)->hour(20)->minute(30)->second(40)->toDateTimeString();
اگه حس میکنید که getterها و setterها جواب نیاز شما هستند حتما به قسمت مربوط به خودشون تو مستندات کربن نگاه بندازید. (getterها در کربن و setterها در کربن)
تعیین فرمت خروجی
اگه میخواید خروجی شما برای کاربرها مناسب باشه کربن متدهایی داره که کمک کننده هستند:
$dt = Carbon::create(1975, 12, 25, 14, 15, 16);
echo $dt->toDateString(); // 1975-12-25
echo $dt->toTimeString(); // 14:15:16
echo $dt->toDateTimeString(); // 1975-12-25 14:15:16
echo $dt->toFormattedDateString(); // Dec 25, 1975
echo $dt->toFormattedDayDateString(); // Thu, Dec 25, 1975
echo $dt->toDayDateTimeString(); // Thu, Dec 25, 1975 2:15 PM
اگه هیچکدوم از متدهای بالا خروجی مورد نظر شما رو تولید نمیکنند اصلا نگران نباشید چون هنوز متد ()format
قابل استفاده هست.
$dt = Carbon::create(1975, 12, 25, 14, 15, 16);
echo $dt->format('l jS \\of F Y h:i:s A'); // Thursday 25th of December 1975 02:15:16 PM
اگه براتون سوال پیش اومده که مقادیر داخل متد ()format
از کجا اومدند حتما یه نگاه به این بخش از مستندات PHP برای تعیین فرمت تاریخ و زمان بندازید.
محاسبه فاصله زمانی
با کربن میتونیم فاصله بین ۲ زمان رو در واحدی که میخوایم مثل روز یا ساعت اندازهگیری کنیم:
$now = Carbon::now();
$future = Carbon::now()->addHours(6);
echo $now->diffInHours($future);
خروجی کد بالا عدد 6
هست ولی بیاید با یک مثال جالبتر این موضوع رو ادامه بدیم:
$dtToronto = Carbon::createMidnightDate(2021, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createMidnightDate(2021, 1, 1, 'America/Vancouver');
echo $dtToronto->diffInHours($dtVancouver);
echo $dtVancouver->diffInHours($dtToronto);
اگر به خروجی نیاز داشته باشیم که برای انسانها واضح تر باشه اونوقت ()diffForHumans
جواب کار ما هست:
echo Carbon::now()->subDays(5)->diffForHumans(); // 5 days ago
ادغام در لاراول
مهمترین نکته برای ادغام پکیج کربن با فریمورک لاراول نحوه تبدیل مقدار تاریخی که در دیتابیس ذخیره شده به Object
کربن هست که امروزه این کار در لاراول با کمک مفهوم casting خیلی راحتتر شد:
class Post extends Model {
protected $casts = [
'published_at' => 'datetime',
];
}
دقت کنید که ستونهای created_at
و updated_at
در لاراول به صورت پیشفرض به Object
کربن تبدیل میشن و ما کافیه به فکر ستونهای دیگه باشیم که لازم هست به date
یا datetime
تبدیل بشن.
سفر به اعماق لاراول
برای درک بهتر ادغام لاراول و کربن بهتره که به اعماق کدهای لاراول بریم، اما قبل از آن اگر به مستندات لاراول نگاه کنیم با ۲ تابع کمکی()now
و ()tomorrow
روبرو میشم. این توابع در اصل از Carbon استفاده میکنند و طبق چیزی که تو کدهای لاراول در مسیر Illuminate\Foundation\helpers.php
میبینیم اونها Object
کربن برگشت میدن:
در این تابع کلاس Date
وجود داره که در ابتدای فایل فراخوانی شده:
use Illuminate\Support\Facades\Date;
و اگر به فایلی که Date در اون تعریف شده بریم میبینیم که کلاس اصلی براساس DEFAULT_FACADE
در متد resolveFacadeInstance
تعیین شده که اسمش DateFactory
هست.
الان لازمه که وارد DateFactory در مسیر Illuminate/Support/DateFactory.php
بشیم تا بفهمیم متد ()now
چطور کار میکنه، اگه به طور کامل DateFactory
رو بررسی کنیم میبینیم که هیچ متدی با نام()now
اونجا وجود نداره بنابراین متدجادویی(Magic Method) ()call__
اجرا میشه.
در ()call__
مقدارdateClass$
وجود داره که Illuminate\Support\Carbon
در اون تعریف شده و بررسی میشه که آیا متدی که دنبالش هستیم(مثلا ()now
) در Illuminate\Support\Carbon
وجود داره یا اینکه به صورت macro تعیین شده و اگر متد مورد نظر ما وجود داشت فراخوانی و اجرا میشه.
باتوجه به نتایج بدست اومده لازمه وارد فایل Illuminate/Support/Carbon.php
بشیم و در اونجا میبینیم که این کلاس در واقع یک نگهدارنده برای کلاس والد خودش(کلاس Carbon
) هست و اجازه میده که بتونیم کارهایی مثل تعریف macro انجام بدیم.
الان وارد پکیج کربن میشیم یعنی جایی که کلاس Carbon تعریف شده و اونجا میبینیم که کلاس Carbon
از کلاس DateTime
در PHP ارثبری کرده ولی اگه دقت کنید میبینید که هیچ متد دیگهای وجود نداره و این سوال برای ما پیش میاد که واقعا بقیه متدها کجا تعریف شدند؟
خب دنبال متدی مثل ()now
در این فایل گشتیم و دیدیم که در این کلاس یک متد بیشتر وجود نداره و میدونیم که در کلاس DateTime
هم متدی با نام ()now
وجود نداره ولی اگر بیشتر دقت کنیم میبینیم که در این کلاس از trait
با نام Date
استفاده شده که امکان داره متدهای ما اونجا تعریف شده باشند.
وارد trait
مورد نظر خودمون یعنی Date میشیم و میبینیم که در اونجا هم تابع ()now
وجود نداره ولی trait
های مختلفی در اون تعریف شدند که اسم یکی از اون trait
ها Creator
هست پس بهتره مستقیما واردش بشیم.
اینجا پایان مسیر شگفتانگیز ما هست یعنی جایی که متدهای مورد نظر ما مثل ()now یا ()today تعریف شدند.
همونطور که متوجه شدیم کلاس Carbon\Carbon
در لاراول توسط Illuminate\Support\Carbon
پیچیده شده که قابلیت Macroable بودن رو به تاریخ و زمان در لاراول اضافه کرده. (pull request مربوط به این ویژگی)
به انتهای مقاله رسیدیم و با ویژگیهای اصلی پکیج Carbon آشنا شدیم و میتونیم تو اکثر پروژهها با اطمینان خاطر ازش استفاده کنیم و درکنارش تونستیم با سفر به اعماق کربن و لاراول ادغامش با لاراول رو درک کنیم.
از اونجایی که این پکیج بسیار غنی هست اصلا نباید از مستنداتش غافل شد و در جایگاه یک توسعهدهنده باید بتونیم برای نیازهای پروژه به مستندات سر بزنیم و نیاز مورد نظر رو از اونجا استخراج کنیم.
مطلبی دیگر از این انتشارات
لاراول Pdf ، کاراکتر فارسی دغدغه نیست !
مطلبی دیگر از این انتشارات
اشتباهات رایج در طراحی دیتابیس - قسمت اول
مطلبی دیگر از این انتشارات
پیاده سازی نوتیفیکیشن ها با لاراول