Philipp Mochine
Philipp Mochine

Reputation: 4715

How to cast time in Laravel?

I'm trying to get a TimeString from 08:00:00 to 08:00.

I would like to cast time like this:

protected $casts = [
    'opens' => 'time:H:i',
    'closes' => 'time:H:i',
];

without using mutators like getOpensAttribute().

In my migration I'm using:

$table->time('opens')->nullable();
$table->time('closes')->nullable(); 

Is it possible?

Upvotes: 11

Views: 14556

Answers (4)

Ezequiel García
Ezequiel García

Reputation: 2776

i think you can create a custom cast for example:

Generate a custom cast with:

php artisan make:cast TimeCast

TimeCast

public function get($model, string $key, $value, array $attributes)
{
    return  Carbon::parse($value)->format('H:i');
}

finally you can use it as

protected $casts = [
    'your_time_to_cast' => TimeCast::class
];

Upvotes: 13

Robin Bastiaan
Robin Bastiaan

Reputation: 702

You can achieve this by defining an accessor on your model like so:

protected function opens(): Attribute
{
    return Attribute::make(
        get: fn($value) => Carbon::createFromFormat('H:i:s', $value)->format('H:i'),
    );
}

protected function closes(): Attribute
{
    return Attribute::make(
        get: fn($value) => Carbon::createFromFormat('H:i:s', $value)->format('H:i'),
    );
}

Depending on your needs you might want to also add the name of this attribute to the $appends property to make it visible when serializing your model:

protected $appends = ['opens', 'closes'];

Please note that my syntax is valid for Laravel version 9+. For older versions, use the below syntax instead:

public function getOpensAttribute($value)
{
    return Carbon::createFromFormat('H:i:s', $value)->format('H:i');
}
public function getClosesAttribute($value)
{
    return Carbon::createFromFormat('H:i:s', $value)->format('H:i');
}

Upvotes: 1

Red Bayoub
Red Bayoub

Reputation: 11

What I ended up doing is overriding toArray() method on the model here's an example from my code from inside the model file

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class City extends Model
{
 use HasFactory;

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'name',
];

/* this is the related part */
public function toArray()
{
    $array = parent::toArray();
    $array['starts_at'] = $array['starts_at']->format('H:i:s');
    $array['ends_at'] = $array['ends_at']->format('H:i:s');
    return $array;
}

}

Upvotes: 0

Chris C.
Chris C.

Reputation: 423

According to the docs, the only supported cast types are:

integer, real, float, double, string, boolean, object, array, collection, date, datetime, and timestamp.

Therefore you have to convert your time to string either before you store it or after you retrieve it from the database.

Upvotes: 1

Related Questions