PHP Version
8.3
CodeIgniter4 Version
4.7.2
CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter)
Which operating systems have you tested for this bug?
Linux
Which server did you use?
apache
Environment
development
Database
Not relevant
What happened?
When using CodeIgniter\Entity\Entity::injectRawData() with a PHP enum (UnitEnum / BackedEnum), an infinite recursion or unexpected behavior occurs if the enum defines a toArray() method.
This is caused by the order of checks in Entity::normalizeValue():
} elseif (method_exists($data, 'toArray')) {
$objectData = $data->toArray();
} elseif ($data instanceof UnitEnum) {
Because method_exists($data, 'toArray') is evaluated before checking for UnitEnum, enums that define a toArray() method are treated as generic objects instead of enums.
This leads to recursive normalization and may result in infinite loops or excessive processing.
Steps to Reproduce
- Create an enum with a toArray() method:
enum TestRawEnum: string
{
case TEST = 'test';
case IN_REVIEW = 'in_review';
public function toArray(): array
{
return [
self::TEST,
self::IN_REVIEW,
];
}
}
- Use it in an Entity:
$e = new \CodeIgniter\Entity\Entity();
$e->injectRawData([
'test' => TestRawEnum::TEST,
]);
This triggers normalizeValue() internally via syncOriginal().
Expected Output
Enums should always be handled by the UnitEnum branch: elseif ($data instanceof UnitEnum) regardless of whether they implement toArray() or not.
Actual Behavior:
Enums with a toArray() method are processed by method_exists($data, 'toArray') instead of the UnitEnum handler, causing incorrect normalization and potential recursion issues.
Proposed Fix:
Change the order of checks in normalizeValue() so that enums are handled before toArray():
if ($data instanceof self) {
...
} elseif ($data instanceof UnitEnum) {
return [
'__class' => $data::class,
'__enum' => $data instanceof BackedEnum ? $data->value : $data->name,
];
} elseif ($data instanceof JsonSerializable) {
...
} elseif (method_exists($data, 'toArray')) {
$objectData = $data->toArray();
}
Anything else?
This issue appears whenever enums are extended with helper methods like toArray(), which is a common pattern.
The current implementation assumes that presence of toArray() means the object should be treated as a generic value object, which conflicts with PHP enum behavior.
PHP Version
8.3
CodeIgniter4 Version
4.7.2
CodeIgniter4 Installation Method
Composer (using
codeigniter4/appstarter)Which operating systems have you tested for this bug?
Linux
Which server did you use?
apache
Environment
development
Database
Not relevant
What happened?
When using CodeIgniter\Entity\Entity::injectRawData() with a PHP enum (UnitEnum / BackedEnum), an infinite recursion or unexpected behavior occurs if the enum defines a toArray() method.
This is caused by the order of checks in Entity::normalizeValue():
Because method_exists($data, 'toArray') is evaluated before checking for UnitEnum, enums that define a toArray() method are treated as generic objects instead of enums.
This leads to recursive normalization and may result in infinite loops or excessive processing.
Steps to Reproduce
This triggers normalizeValue() internally via syncOriginal().
Expected Output
Enums should always be handled by the UnitEnum branch:
elseif ($data instanceof UnitEnum)regardless of whether they implementtoArray()or not.Actual Behavior:
Enums with a
toArray()method are processed bymethod_exists($data, 'toArray')instead of theUnitEnumhandler, causing incorrect normalization and potential recursion issues.Proposed Fix:
Change the order of checks in
normalizeValue()so that enums are handled before toArray():Anything else?
This issue appears whenever enums are extended with helper methods like
toArray(), which is a common pattern.The current implementation assumes that presence of
toArray()means the object should be treated as a generic value object, which conflicts with PHP enum behavior.