JsonObjectKeyOrderPreserver
Workaround for form_definition.configuration being persisted through a native SQL JSON column (TCA type=json).
Multi-value form elements (SingleSelect, MultiSelect, RadioButton, MultiCheckbox, ...) store their "options" as an associative map (value => label) keyed by option value. json_encode() of such a map produces a JSON object, and MySQL's native JSON column type does not guarantee that a JSON object's member order survives a write/read round trip. This is documented, spec-compliant behavior (RFC 8259: object member order "has no significance"). JSON array element order, by contrast, is reliably preserved by MySQL.
MariaDB's JSON type is a plain LONGTEXT alias with a CHECK(JSON_VALID(...)) constraint, so it happens to preserve the exact text (and therefore object member order) byte-for-byte, which is why this only reproduces on real MySQL.
Practical effect without this workaround: reordering a select element's options in the form editor visibly "works" right after saving, but reverts to the previous order on the next reload, once MySQL has renormalized the JSON object.
protect() wraps every "options" map in an array-based structure before persisting, so the intended order survives via a JSON array instead of relying on object member order. restore() reverses this again after json_decode() on read, using the explicit order list rather than the member order MySQL happened to return the object in.
Note: "options" is matched by key name rather than by resolving each renderable's prototype configuration for declared multi-value properties (as FormEditorController does for the editor UI). This is a deliberate simplification. It also protects option order inside variant overrides for free, without needing prototype/DI wiring in the persistence layer and is safe even where it over-applies, since protect()/restore() are lossless no-ops on any "options" map that doesn't need reordering.
Table of Contents
Methods
Methods
protect()
public
protect(array<string|int, mixed> $formDefinition) : array<string|int, mixed>
Parameters
- $formDefinition : array<string|int, mixed>
Return values
array<string|int, mixed>restore()
public
restore(array<string|int, mixed> $formDefinition) : array<string|int, mixed>
Parameters
- $formDefinition : array<string|int, mixed>