Entity attributes and type resolution¶
Small Forms can derive an inline form from an object:
Internally this creates an AnnotationAdapter and inspects the object's properties.
Explicit form metadata on an entity¶
A property can carry ORM metadata and Small Forms metadata side by side:
use Small\Forms\Form\Field\Type\StringType;
use Small\Forms\Modifier\EmptyStringToNullModifier;
use Small\Forms\ValidationRule\ValidateEmail;
use Small\SwooleEntityManager\Entity\Attribute\Field;
use Small\SwooleEntityManager\Entity\Enum\FieldValueType;
#[Field(type: FieldValueType::string)]
#[StringType]
#[EmptyStringToNullModifier]
#[ValidateEmail]
private ?string $email = null;
The explicit Small Forms type has priority over automatic type resolution.
Type-resolution order¶
AbstractObjectAdapter::getType() resolves each property in this order:
- the first property attribute whose object extends
AbstractType; - exact native
bool,int,float,arrayorstringtypes; - the initialized property value when it is a Small Collection or array;
- the initialized property value when it implements
DateTimeInterface; - another initialized object value, mapped to
SubFormType; - otherwise
UnknownTypeException.
FormBuilder::createFromAdapter() catches UnknownTypeException and skips that property.
Use explicit types on ORM entities
Nullable scalar types such as ?string stringify as ?string through reflection and therefore do not match the adapter's exact scalar cases. Nullable relations that currently contain null also cannot be inferred from their value. Put an explicit Small Forms type attribute on writable ORM properties instead of relying on inference.
For example:
Without #[StringType], that nullable property can be omitted from the generated form.
Relation properties¶
Use explicit nested form types for relations:
#[ToOne(AddressManager::class, ['addressId' => 'id'])]
#[SubFormType(AddressEntity::class)]
private ?AddressEntity $address = null;
For arrays/nested lists:
Entity Manager to-many relations normally use EntityCollection; see Relations and nested forms before relying on automatic hydration of the stock collection.
Validation and modifier attributes¶
AnnotationAdapter collects property attributes implementing:
ValidationRuleInterfaceinto the field's validation rules;ModifierInterfaceinto the field's modifiers.
All built-in Small Forms 2.3 validators and modifiers are declared as PHP attributes with property-target support. This includes the complete catalog of 75 validation rules and 38 modifiers documented in the validation-rule reference and modifier reference.
That means rules and transformations can be expressed directly on an ORM entity property:
use Small\Forms\Form\Field\Type\StringType;
use Small\Forms\Modifier\SubStrModifier;
use Small\Forms\Modifier\ToLowerModifier;
use Small\Forms\Modifier\TrimModifier;
use Small\Forms\ValidationRule\ValidateBeginWith;
use Small\Forms\ValidationRule\ValidateNumberCharsAtLeast;
use Small\SwooleEntityManager\Entity\Attribute\Field;
use Small\SwooleEntityManager\Entity\Enum\FieldValueType;
#[Field(type: FieldValueType::string)]
#[StringType]
#[TrimModifier]
#[ToLowerModifier]
#[SubStrModifier(0, 64)]
#[ValidateBeginWith('usr-')]
#[ValidateNumberCharsAtLeast(8)]
private string $externalId = '';
The same classes remain usable programmatically through addField(), addRule() and addModifier(). ValidateCallback is technically an attribute class too, but its Closure constructor argument makes normal programmatic construction the practical choice.
ORM attributes such as Field, PrimaryKey, ToOne and ToMany are ignored by the Small Forms rule/modifier collectors because they do not implement those interfaces.
The adapter also verifies that attribute classes exist. Attribute-driven forms therefore surface invalid/missing attribute classes early.
Symfony Validator dependency¶
The current AnnotationAdapter checks for Symfony\Component\Validator\Validation in its constructor. Install the package when using object/attribute forms:
Small Forms does not translate Symfony Assert\* constraints into Small Forms validators. The dependency is currently a runtime requirement of AnnotationAdapter, not an alternate validation engine.