gundogduyakici created_at, updated_at ve modelde date/datetime olarak cast yaptığınız özellikler otomatik olarak Carbon objesine dönüştürüldüğü için direkt şöyle yapabilirsiniz:
{{ $model->created_at->tz('Europe/Istanbul') }}
Eğer sürekli timezone yazmak istemiyorsanız ya da timezone bilgisini giriş yapmış kullanıcıdan alıyorsanız şu şekilde bir yol önerebilirim:
app/Services/Timezone.php:
final class Timezone
{
private static ?string $tz = null;
public static function get(): ?string
{
return self::$tz;
}
public static function set(?string $tz = null): void
{
self::$tz = $tz;
}
}
Bir tane middleware oluşturun:
php artisan make:middleware SetTimezone
app/Http/Middleware/SetTimezone.php;
public function handle(Request $request, Closure $next)
{
// Kullanıcının timezone alanı varsa onu kullansın yoksa Europe/Istanbul kullansın. İsterseniz
// config/app.php içerisine 'frontend_timezone' => 'Europe/Istanbul' eklersiniz ve burada
// $request->user()?->timezone ?? config('app.frontend_timezone') kullanırsınız.
Timezone::set($request->user()?->timezone ?? 'Europe/Istanbul');
return $next($request);
}
SetTimezone middleware'ini \App\Http\Kernel::$middlewareGroups içindeki web anahtarının en altında ekliyorsunuz:
protected $middlewareGroups = [
'web' => [
...
\App\Http\Middleware\SetTimezone::class
],
Bir tane custom cast oluşturun:
php artisan make:cast DatetimeTz
namespace App\Casts;
use App\Services\Timezone;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Facades\Date;
class DateTimeTz implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
$tz = Timezone::get();
return Date::parse($value)->tz($tz);
}
public function set($model, string $key, $value, array $attributes)
{
return $value;
}
}
Artık yapmanız gereken kullanacağınız modelde protected $casts içerisinde tarihleri DatetimeTz olarak göstermek. Mesela app/Models/User.php:
protected $casts = [
'email_verified_at' => DateTimeTz::class,
'created_at' => DateTimeTz::class,
'updated_at' => DateTimeTz::class,
];
Artık Blade içerisinde {{ $model->created_at }}
yaptığınızda tarih otomatik olarak verilen zaman diliminde gelecek.
---
Elbette bu sadece Blade içerisinde ekrana basarken çalışır. Eğer model serialize olurken de (örneğin API yazıyorsanız, veriyi bir frontend framework kullanacaksa) aynı şekilde değişmesini istiyorsanız modele ayrıca şunu eklemeniz lazım:
protected function serializeDate(DateTimeInterface $date)
{
return $date->format(DateTime::ATOM);
}
Bu yolu önermiyorum, sadece bilgi amaçlı yazdım. Model serialize olurken tarihler mutlaka UTC dönmeli, istemci dönüştürme işini gerçekleştirmeli. Siz Blade kullandığınız için aynı zamanda bir istemci gibi davranmış oluyorsunuz.