Skip to content

fix: toRawArray() should convert DateTime objects to strings#10207

Open
jalexiscv wants to merge 1 commit into
codeigniter4:developfrom
jalexiscv:fix/bug-8302-toRawArray-datetime
Open

fix: toRawArray() should convert DateTime objects to strings#10207
jalexiscv wants to merge 1 commit into
codeigniter4:developfrom
jalexiscv:fix/bug-8302-toRawArray-datetime

Conversation

@jalexiscv
Copy link
Copy Markdown

Description

Fixes #8302 - Entity::toRawArray() may return Time object

Problem

When a date field is set on an Entity (e.g., $user->updated_at = "2023-12-12 12:12:12"), the __set() method converts it to a Time object via mutateDate(). However, toRawArray() was returning $this->attributes directly without converting Time/DateTime objects back to strings.

$user->updated_at = "2023-12-12 12:12:12";
var_dump($user->toRawArray());
// Before fix: "updated_at" => Time object (BUG)
// After fix:  "updated_at" => "2023-12-12 12:12:12" (string)

Solution

Three changes in Entity::toRawArray():

  1. Add DateTimeInterface check at the top of the $convert closure, converting DateTime objects to strings via __toString()
  2. Always apply array_map($convert, ...) to attributes in the !onlyChanged path instead of returning $this->attributes directly
  3. Apply $convert() to non-recursive changed values too

toArray() behavior is unchanged — it still returns Time objects.

Changes

One file: system/Entity/Entity.php

  • Added DateTimeInterface → string conversion in convert closure
  • Changed !onlyChanged return to always use array_map
  • Changed non-recursive changed value assignment to use $convert

Testing

  • toRawArray() returns all string/primitive values ✓
  • toRawArray(true) (onlyChanged) returns no objects ✓
  • toArray() still returns Time objects (no regression) ✓

Ref: #8302
Closes #8302

@mergeable
Copy link
Copy Markdown

mergeable Bot commented May 18, 2026

Hi there, jalexiscv! 👋

Thank you for sending this PR!

We expect the following in all Pull Requests (PRs).

Important

We expect all code changes or bug-fixes to be accompanied by one or more tests added to our test suite to prove the code works.

If pull requests do not comply with the above, they will likely be closed. Since we are a team of volunteers, we don't have any more time to work
on the framework than you do. Please make it as painless for your contributions to be included as possible.

See https://github.com/codeigniter4/CodeIgniter4/blob/develop/contributing/pull_request.md

Sincerely, the mergeable bot 🤖

@jalexiscv jalexiscv force-pushed the fix/bug-8302-toRawArray-datetime branch from d486216 to b7f0796 Compare May 18, 2026 03:05
Copy link
Copy Markdown
Contributor

@neznaika0 neznaika0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need tests, guide update...
I disagree with the convert. I prefer objects in attributes in my code. Including for the date. Now the attributes will contain strings instead of an object.

Fixes codeigniter4#8302

When a date field is set on an Entity, __set() converts it to a Time
object via mutateDate(). However, toRawArray() returned attributes
directly without converting Time/DateTime objects back to strings.

This fixes toRawArray() to return primitive types by converting
DateTimeInterface objects to strings via __toString(). The underlying
$this->attributes remain unchanged (still contain Time objects).
toArray() behavior is preserved (still returns Time objects).

Changes:
- Entity::toRawArray(): DateTimeInterface objects converted to strings
- Added test verifying:
  * toRawArray() returns strings for date fields
  * $this->attributes still contain Time objects
  * toArray() still returns Time objects (no regression)

Ref: codeigniter4#8302
@jalexiscv jalexiscv force-pushed the fix/bug-8302-toRawArray-datetime branch from b7f0796 to 67a42dc Compare May 18, 2026 03:58
@jalexiscv
Copy link
Copy Markdown
Author

Thanks for the review @neznaika0!

I've added a unit test (testToRawArrayConvertsDateTimeToString) that verifies:

  1. toRawArray() returns strings for date fields ✓
  2. $this->attributes still contain Time objects (unchanged) ✓
  3. toArray() still returns Time objects (no regression) ✓

Full test suite: 139 tests, all passing.

Clarification on the conversion: The change only affects the output of toRawArray()$this->attributes are never modified. They still contain Time objects. The toRawArray() method is designed to return raw/primitive values (as its name implies), while toArray() keeps returning Time objects.

So your code that expects objects in attributes continues to work exactly as before. Only the serialized/raw output is affected.

@neznaika0
Copy link
Copy Markdown
Contributor

neznaika0 commented May 18, 2026

This has not been the case for a long time. The primitives were before version ~4.5. Now attributes can contain any data (using DataCaster in the entity or DataConverter for models). For understanding, after selecting the Model::find(), an entity can convert a date string into an object. Therefore, toRowArray() will contain more than just primitives. Look at the tests.

See

public function testCastIntBool(): void

Original attribute is string, raw data is integer.

@paulbalandan paulbalandan added the bug Verified issues on the current code behavior or pull requests that will fix them label May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Verified issues on the current code behavior or pull requests that will fix them

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Entity::toRawArray() may return Time object

3 participants