Database definition
status ENUM('ACTIVE','PENDING','EXPIRED') DEFAULT NULL
Generated Entity
PHPMaker generates a setter similar to this:
public function setStatus(string $value): static
{
if (!in_array($value, ["ACTIVE", "PENDING", "EXPIRED"])) {
throw new InvalidArgumentException("Invalid 'status' value");
}
$this->status = $value;
return $this;
}
Problem
When the field is left empty (or the application passes NULL), the generated setter throws an InvalidArgumentException, even though the database column explicitly allows NULL.
This makes nullable ENUM fields unusable through the generated Entity API.
Expected behavior
If the database column is nullable, the generated setter should also allow NULL.
For example:
public function setStatus(?string $value): static
{
if ($value !== null && !in_array($value, ["ACTIVE", "PENDING", "EXPIRED"], true)) {
throw new InvalidArgumentException("Invalid 'status' value");
}
$this->status = $value;
return $this;
}
Notice that:
-
The parameter type should be
?stringinstead ofstring. -
Validation should only be performed when the value is not
NULL.
Why this matters
This issue causes runtime exceptions whenever an optional ENUM field is submitted empty, despite the database schema allowing NULL.
It appears that the code generator ignores the column's nullability when generating Entity setters.
Suggested fix
// @phpmaker\php2026\entity.php
<# if (f.FldTypeName == 'enum') { #>
<# if (IsBooleanField(f)) { // Handle boolean field #>
$value = ConvertToBool($value) ? '<#= Code.quote(TrueValue) #>' : '<#= Code.quote(FalseValue) #>';
<# } #>
//..
<# if (f.isNullable) { #>
if ($value !== null && !in_array($value, [<#= f.fldValues #>], true)) {
<# } else { #>
if (!in_array($value, [<#= f.fldValues #>], true)) {
<# } #>
throw new InvalidArgumentException("Invalid '<#= f.FldName #>' value");
}
//..
$this-><#= f.propertyName #> = $value;
<# } #>
Reason
- Nullable
ENUMcolumns should acceptNULLwithout throwing an exception. - Validation should only be performed when a non-
NULLvalue is provided. - Using
in_array(..., true)performs a strict comparison and avoids unintended type coercion.
I also noticed a similar improvement for SET fields. Although it doesn't have the same nullable issue, it should also use strict comparison:
Current:
!in_array($v, [<#= f.fldValues #>])
Suggested:
!in_array($v, [<#= f.fldValues #>], true)
This makes the generated validation more type-safe and consistent.