CoolCMS API

ColumnLimits
in package

FinalYes

Single source of truth for column limits used by validation gates.

The schema declares length/precision/scale on many columns, but nothing enforces them: the hydrator ignores them, DecimalType::convertToDatabaseValue() is a passthrough and the database outcome depends on sql_mode: strict fails the whole save with a generic database error, non-strict throws no exception and silently truncates ('abc' becomes 0.000, 25 characters into varchar(20) are cut). Every write path therefore has to guard the limits itself, and when each path copied them by hand, a gate sooner or later measured a different number than the column holds.

The limits are read by reflection from the #[ORM\Column] attribute of the entity, the same place Doctrine reads them from. After a schema change (migration + entity) the gates follow on their own. Works with promoted constructor properties too, which most entities use.

Usage in a form:

$form->addText('email', …)
    ->addRule($form::MAX_LENGTH, $t('email.rules.long'), ColumnLimits::length(User::class, 'email'));

Table of Contents

Properties

$cache  : array<string, array<string, array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}>>

Methods

decimalMaxExclusive()  : numeric-string
Returns the upper bound of a decimal column as an exclusive limit in decimal notation (`10^(precision-scale)`).
decimalPrecision()  : int
Returns the total number of digits of a decimal column (`precision`).
describe()  : array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}|null
Describes the column of a property, or returns null when the entity has no such property or it is not a `#[ORM\Column]` (a relation, a transient field). For a form gate that maps controls to columns by name ({@see \App\Core\Forms\ColumnGate::guard()}), where "not a column" is a normal answer, not a typo.
integerRange()  : array{0: int, 1: int}
Returns the inclusive range of an integer column (`smallint`/`integer`/`bigint`, signed or `unsigned`), the bounds of the MySQL type.
length()  : int
Returns the maximum number of characters of a column (`length` from `#[ORM\Column]`).
scale()  : int
Returns the number of decimal places of a column (`scale`).
read()  : array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}

Properties

$cache

private static array<string, array<string, array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}>> $cache = []

Methods

decimalMaxExclusive()

Returns the upper bound of a decimal column as an exclusive limit in decimal notation (`10^(precision-scale)`).

public static decimalMaxExclusive(class-string $entity, string $property) : numeric-string

Returns a string on purpose: (float) overflows to INF for large values and any comparison with it lies. Compare with bcmath over the value after rounding, that is, over what is actually written, not over the raw input.

Parameters
$entity : class-string
$property : string
Return values
numeric-string

decimalPrecision()

Returns the total number of digits of a decimal column (`precision`).

public static decimalPrecision(class-string $entity, string $property) : int
Parameters
$entity : class-string
$property : string
Return values
int

describe()

Describes the column of a property, or returns null when the entity has no such property or it is not a `#[ORM\Column]` (a relation, a transient field). For a form gate that maps controls to columns by name ({@see \App\Core\Forms\ColumnGate::guard()}), where "not a column" is a normal answer, not a typo.

public static describe(class-string $entity, string $property) : array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}|null

The type falls back to the PHP type of the property when the attribute omits it (Doctrine infers it the same way); a string without length is 255, the Doctrine default.

Parameters
$entity : class-string
$property : string
Return values
array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}|null

integerRange()

Returns the inclusive range of an integer column (`smallint`/`integer`/`bigint`, signed or `unsigned`), the bounds of the MySQL type.

public static integerRange(class-string $entity, string $property) : array{0: int, 1: int}

A form integer field without it let 99999999999 through Form::INTEGER; strict sql_mode then failed the whole save with a generic database error, non-strict stored the type maximum.

NOTE: bigint is capped at PHP_INT_MAX, the largest value a form integer can carry anyway.

Parameters
$entity : class-string
$property : string
Return values
array{0: int, 1: int}

length()

Returns the maximum number of characters of a column (`length` from `#[ORM\Column]`).

public static length(class-string $entity, string $property) : int
Parameters
$entity : class-string
$property : string
Tags
throws
ReflectionException

when the property does not exist; a typo in the name must show up immediately, not as a silent truncation in production

Return values
int

scale()

Returns the number of decimal places of a column (`scale`).

public static scale(class-string $entity, string $property) : int
Parameters
$entity : class-string
$property : string
Return values
int

read()

private static read(class-string $entity, string $property) : array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}
Parameters
$entity : class-string
$property : string
Tags
throws
ReflectionException
Return values
array{length: int|null, precision: int|null, scale: int|null, type: string|null, unsigned: bool}
On this page

Search results