مدیریت منطقه ‌های زمانی (timezone) کاربر در لاراول

در این مقاله از لیداوب، چگونگی مدیریت منطقه‌های زمانی (timezone) برای هر کاربر در لاراول توضیح داده شده است.


در ادامه، قصد داریم در یک پروژه کوچک، نحوه کار با مناطق زمانی (timezones) در لاراول را به شما نمایش دهیم. صفحه ثبت نام کاربر یک فیلد Timezone دارد که هر کاربر می‌تواند در آن داده‌هایش را در منطقه زمانی خود مشاهده ‌کند.

مدیریت منطقه ‌های زمانی (timezone) کاربر در لاراول

چیزی که ما نیاز داریم، سیستم مدیریت رویداد با یک فیلد events.start_time است که در UTC timezone در پایگاه داده ذخیره می‌شود و در صورت نیاز مورد استفاده قرار می‌گیرد. در ساخت این پروژه تا حدودی از QuickAdminPanel generator استفاده شده است. ما در این مطلب، کدهای مربوط به موضوع timezone را توضیح می‌دهیم. شما می‌توانید تمام کدهای مربوط به این پروژه را در Github مشاهده کنید.

مرحله اول: فرم ثبت نام

در مرحله اول، ما درون پایگاه داده خود نیاز به یک ستون timezone  به عنوان یک رشته با مقدار پیش‌فرض Europe/London داریم:

Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('timezone')->default('Europe/London');
$table->rememberToken();
$table->timestamps();
});

سپس، در مدل app/User.php آن را به صورت فیلدی که باید پر شود، اضافه می‌کنیم:

class User extends Authenticatable
{
use Notifiable;
protected $fillable = ['name', 'email', 'password', 'remember_token', 'timezone'];
// ... other model code

پس از آن، در ویوی registration آن را به عنوان یک فیلد کشویی اضافه می‌کنیم:

laravel-timezone

برای انجام این کار، می‌توانید از پکیج camroncade/timezone استفاده کنید. همچنین، می‌توانید در app/Http/Controllers/Auth/RegisterController.php خود متد showRegistrationForm () را به صورت زیر بازنویسی کنید که در اصل در ویژگی RegistersUsers قرار دارد:

/**
* Show the application registration form.
*
* @return \Illuminate\Http\Response
*/
public function showRegistrationForm()
{
$timezone_select = Timezone::selectForm(
'Europe/London', 
'', 
['class' => 'form-control', 'name' => 'timezone']
);
return view('auth.register', compact('timezone_select'));
}

سپس در فایل resources/views/auth/register.blade.php فقط از یک متغیر برای نمایش کشویی این فیلد استفاده می‌کنیم:

{!! $timezone_select !!}

در آخر، در فایل app/Http/Controllers/Auth/RegisterController.php متد create() را برای ذخیره منطقه زمانی به صورت زیر بازنویسی می‌کنیم:

/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
'timezone' => $data['timezone'],
]);

return $user;
}

مرحله دوم: ذخیره رویداد در منطقه زمانی کاربر

در فرم اضافه کردن رویداد، یک datetime picker ساده و بدون هیچ منطقه زمانی وجود دارد. بنابراین، فرض می‌کنیم که کاربر زمان را در منطقه زمانی خودش وارد می‌کند.

laravel-timezone

در هنگام ذخیره زمان، ما از تابع mutator Eloquent لاراول در فایل app/Event.php به صورت زیر استفاده می‌کنیم:

use Camroncade\Timezone\Facades\Timezone;
// ...

/**
* Set attribute to date format
* @param $input
*/
public function setStartTimeAttribute($input)
{
$this->attributes['start_time'] =
Timezone::convertToUTC($input, auth()->user()->timezone, 'Y-m-d H:i:s');
}

مطالعه مقالات بیشتر در لیداوب:

مرحله سوم: مشاهده رویداد در منطقه زمانی کاربر

مرحله نهایی، مشاهده لیست رویدادها در منطقه زمانی کاربر است. بنابراین، اگر یک رویداد توسط یک کاربر در لندن وارد شود و بخواهید کاربر دیگری در سان فرانسیسکو آن را مشاهده کند، چه کار می‌کنید؟

ما از تابع Eloquent accessor لاراول برای این منظور استفاده می‌کنیم، دوباره در فایل app/Event.php متد زیر را اضافه می‌کنیم:

/**
* Get attribute from date format
* @param $input
*
* @return string
*/
public function getStartTimeAttribute($input)
{
return Timezone::convertFromUTC($input, auth()->user()->timezone, 'Y-m-d H:i:s');
}

اکنون، باید یک لیست ایجاد کنید، بنابراین در app/Http/Controllers/Admin/EventsController.php به صورت زیر عمل می‌کنیم:

public function index()
{
$events = Event::all();
return view('admin.events.index', compact('events'));
}

و در resources/views/events/index.blade.php ، ما یک جدول ساده Blade به صورت زیر خواهیم داشت:

<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>@lang('global.events.fields.title')</th>
            <th>@lang('global.events.fields.start-time')</th>
            <th> </th>

        </tr>
    </thead>

    <tbody>
        @if (count($events) > 0)
            @foreach ($events as $event)
                <tr data-entry-id="{{ $event->id }}">
                    <td field-key='title'>{{ $event->title }}</td>
                        <td field-key='start_time'>{{ $event->start_time }}</td>
                        <td>
                            @can('event_view')
                                <a href="{{ route('admin.events.show',[$event->id]) }}" class="btn btn-xs btn-primary">@lang('global.app_view')</a>
                            @endcan
                            @can('event_edit')
                                <a href="{{ route('admin.events.edit',[$event->id]) }}" class="btn btn-xs btn-info">@lang('global.app_edit')</a>
                            @endcan
                            @can('event_delete')
                                {!! Form::open(array(
                                    'style' => 'display: inline-block;',
                                    'method' => 'DELETE',
                                    'onsubmit' => "return confirm('".trans("global.app_are_you_sure")."');",
                                    'route' => ['admin.events.destroy', $event->id])) !!}
                                {!! Form::submit(trans('global.app_delete'), array('class' => 'btn btn-xs btn-danger')) !!}
                                {!! Form::close() !!}
                            @endcan
                        </td>

                </tr>
            @endforeach
        @else
            <tr>
                <td colspan="7">@lang('global.app_no_entries_in_table')</td>
            </tr>
        @endif
    </tbody>
</table>

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

laravel-timezone

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