Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom datetime casting works, but not if you define custom format #2655

Closed
apeisa opened this issue Oct 31, 2023 · 0 comments
Closed

Custom datetime casting works, but not if you define custom format #2655

apeisa opened this issue Oct 31, 2023 · 0 comments

Comments

@apeisa
Copy link
Contributor

apeisa commented Oct 31, 2023

Thanks to #2653 casting works now, but not in all cases. When using date casts, you can also define the format in the string format, like this (docs):

   protected $casts = [
        'mydate' => 'datetime:j.n.Y H:i',
    ];

When using cast like that, it doesn't work. Without formatting set, it does work as expected:

   protected $casts = [
        'mydate' => 'datetime',
    ];

Here is simple class that can be used for testing:

<?php

namespace App\Models;

use Carbon\Carbon;
use MongoDB\Laravel\Eloquent\Model;

class Car extends Model
{
    protected $guarded = [];

    protected $casts = [
        'sold_at' => 'datetime:j.n.Y H:i',
    ];

    public function sell()
    {
        $this->sold_at = Carbon::now();
        $this->save();
        return $this;
    }
}

And to test this run these commands on Tinker:

> $car = App\Models\Car::create();
= App\Models\Car {#8065
    updated_at: MongoDB\BSON\UTCDateTime {#8071
      +"milliseconds": "1698741994126",
    },
    created_at: MongoDB\BSON\UTCDateTime {#8071},
    _id: MongoDB\BSON\ObjectId {#8075
      +"oid": "6540beea13e41d27cd036b52",
    },
  }

> $car->sell();
= App\Models\Car {#8065
    updated_at: MongoDB\BSON\UTCDateTime {#8063
      +"milliseconds": "1698742000466",
    },
    created_at: MongoDB\BSON\UTCDateTime {#8071
      +"milliseconds": "1698741994126",
    },
    _id: MongoDB\BSON\ObjectId {#8075
      +"oid": "6540beea13e41d27cd036b52",
    },
    sold_at: Illuminate\Support\Carbon @1698742000 {#8066
      date: 2023-10-31 08:46:40.461974 UTC (+00:00),
    },
  }

As you can see the sold_at has Carbon object in database, it should be MongoDB\BSON\UTCDateTime. If you remove the :j.n.Y H:i part from $casts then it works as expected. Here is tinker output without the date formatting:

App\Models\Car {#8065
    updated_at: MongoDB\BSON\UTCDateTime {#8063
      +"milliseconds": "1698742105625",
    },
    created_at: MongoDB\BSON\UTCDateTime {#8071
      +"milliseconds": "1698742103464",
    },
    _id: MongoDB\BSON\ObjectId {#8075
      +"oid": "6540bf576b0d0e380a0cd942",
    },
    sold_at: MongoDB\BSON\UTCDateTime {#8078
      +"milliseconds": "1698742105624",
    },
  }

Originally posted by @apeisa in #2653 (comment)

GromNaN added a commit that referenced this issue Nov 8, 2023
As mentioned in the #2655 issue, casting date types with a custom format did not work properly. So I decided to cover all date types and fix this issue.
I tested these date types:

- immutable_date
- immutable_date with custom formatting
- immutable_datetime
- immutable_datetime with custom formatting
To achieve this goal, I override one of the cases in castAttribute method to handle immutable_date date type. Also, I override transformModelValue method to check if the result is a DateTimeInterface or not for applying defined custom formatting on the Carbon instance and resetting time in a custom date type.
In the end, I should say that all date values will be stored in DB as Date type. (not as an object or string anymore)

---------

Co-authored-by: Jérôme Tamarelle <jerome@tamarelle.net>
@GromNaN GromNaN closed this as completed Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants