Closed vHeemstra closed 1 year ago
Thank you for reporting this issue!
As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.
If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.
Thank you!
@vHeemstra could you link to a repo that shows this is failing?
I tried to write a test case and it's not failing. https://github.com/cosmastech/laravel-framework/pull/1/files Do I have some part of the setup wrong? It could be that it's using SQLite instead of MySQL 🤷 but I'll admit I feel that's not the issue.
Just FYI, I had a very similar thing with Datetime to Timestamp, where casting just wouldn't work.
Workaround was to write a mutator as per https://laravel.com/docs/10.x/eloquent-mutators#defining-a-mutator.
Sorry I can't offer anything more helpful!
@cosmastech I will try to create a working example.
It might be that MySQL is needed, because the Exception is thrown even before any SQL query is sent. Using:
DB::enableQueryLog();
try {
$user->save();
} catch (\Exception $e) {}
dd(DB::getQueryLog());
The dd
'ed result was an empty array, so I guess the DB grammar/adopter (idk) checks all of this before sending the query and there finds the wrong format?
As stated in the report above, the date is correctly filled in the user model instance and becomes a Carbon instance with the correct date. It is just that when compiling/preparing the DB query, the Carbon object is turned into a string using the wrong format (that from $casts
instead of the MySQL one).
Possibly because it might use HasAttributes::attributesToArray()
? Which calls HasAttributes::addCastAttributesToArray
, which calls the format
method on the Carbon instance with the format from $casts
.
@tttogo Thanks, yeah I might do that for the moment. Or switch to Y-m-d
and have front-end rearrange the date. 😄
@vHeemstra could you link to a repo that shows this is failing?
I tried to write a test case and it's not failing. https://github.com/cosmastech/laravel-framework/pull/1/files Do I have some part of the setup wrong? It could be that it's using SQLite instead of MySQL 🤷 but I'll admit I feel that's not the issue.
Repo at: https://github.com/vHeemstra/laravel-date-format-bug
To set it up:
utf8mb4_unicode_ci
).env
php artisan migrate
& php artisan key:generate
php artisan serve
)npm run dev
)d-m-Y
valueThe application worked fine for me.
edit: note, I am running PHP 8.2.4 on Mac OS X & MySQL 8.0.27
@cosmastech First off, thank you so much for taking the time to help!
Second, how strange.. The axios request (when submitting the modal form with a different d-m-Y date) returns with status 200?
I feel OS should not make a difference here. Maybe MySQL versions and/or PHP version, in the way some of the magic getters/setters are implemented??
I just made a new clone from the repo and installed using the steps above. After submitting the edit modal form with only the date set, I still get the described error back from the server:
For completeness, these are the installed dependencies' versions:
composer.json
@tttogo when you were running into this issue, were you using Laravel 10? What version of PHP, DB, etc?
Now I'm getting the error! I was editing my profile, not the Personen edit page.
Found the issue, will put up a PR for this
It seems Taylor has decided to not take any action here, sorry.
But that does not address the issue in the bug report. As Taylor says, the cast format should only be used when model instances become arrays or JSON, but it should not interfere with the way it is stored in the database. (See also the referenced docs in my comment there and in the bug report above.)
But it does interfere. So it is still a bug that needs a fix. (Or the docs need changing.)
I encountered the same problem. Casting with just 'datetime'
and $dateFormat = 'U'
will ensure that both Unix timestamps and Carbon objects are correctly stored, but if you usedatetime:U
and set the value with a Carbon object, it won't be stored correctly.
This is because hasCast()
only looks for datetime
and a few other datetime strings.
To get around this, I implemented a custom cast that accepts both.
Laravel Version
10.6.2
PHP Version
8.1.10
Database Driver & Version
MySQL 10.4.25-MariaDB (using Xampp with Apache) on Windows 11 Pro
Description
When updating a model using a PATCH request, a custom date attribute is not being correctly transformed to the valid MySQL date value. Resulting in the error:
Steps To Reproduce
Database (MySQL)
Column
date_of_birth
is typeDATE
.Migration
The column was created using
$table->date('date_of_birth')
Model
On the default User model, I added the attribute to fillable and set a custom date cast (as described in the docs).
And according to the documentation about date serialization, this should not change the format used for storing it in the database, only the format used in PHP array/JSON model instances.
Steps/flow
d-m-Y
format.d-m-Y
format as well.Route definition in `web.php`
UserUpdateRequest
:`update` method on the controller
```php public function update(UserUpdateRequest $request, User $user) { $user->fill($request->validated()); // dd($user->date_of_birth); <-- Shows it's a Carbon object with the correct value! $user->save(); return response()->json([ 'status' => 'ok', 'user' => $user, ]); } ```Somehow the framework did not correctly turn the Carbon date object into a valid MySQL date representation. So either:
casts
property is wrongly being used hereNote: Setting the model's attribute cast to
date:Y-m-d
does not produce this error. Of course, this is also the exact format MySQL's DATE field uses. This also indicates the issue is option 2.Note 2: Sending/posting the same value as currently in the DB/on the model, does not give an error. (I guess the attribute is skipped in the SQL here because it hasn't changed.)
Update: created example repo
Repo at: https://github.com/vHeemstra/laravel-date-format-bug
To set it up:
utf8mb4_unicode_ci
).env
php artisan migrate
php artisan serve
)npm run dev
)d-m-Y
value