Field Attribute API
The #[Field] attribute marks a property to be populated from HTTP requests.
Definition
namespace Solo\RequestHandler\Attributes;
#[Attribute(Attribute::TARGET_PROPERTY)]
final class Field
{
public function __construct(
public ?string $rules = null,
public ?string $cast = null,
public ?string $mapFrom = null,
public ?string $mapTo = null,
public ?string $preProcess = null,
public ?string $postProcess = null,
public ?string $group = null,
public ?string $generator = null,
public array $generatorOptions = [],
public bool $exclude = false,
public ?string $items = null,
) {}
}Parameters
rules
Validation rules as a pipe-separated string.
| Type | Default |
|---|---|
?string | null |
#[Field(rules: 'required|string|max:255')]
public string $name;
#[Field(rules: 'nullable|email|unique:users,email')]
public ?string $email = null;See Validation for available rules.
cast
Explicit type casting. Overrides automatic casting based on property type.
| Type | Default |
|---|---|
?string | null |
Built-in types:
int,integerfloat,doublebool,booleanstringarraydatetime,datetime:Y-m-d,datetime:immutable,datetime:immutable:Y-m-d
Custom caster:
#[Field(cast: MoneyCaster::class)]
public Money $price;See Type Casting for details.
mapFrom
Dot-notation path to extract value from nested input data.
| Type | Default |
|---|---|
?string | null (uses property name) |
// Request: {"user": {"profile": {"age": 30}}}
#[Field(mapFrom: 'user.profile.age')]
public int $userAge; // 30mapTo
Output key name used in group() instead of the property name. Useful for mapping PHP property names to database column names or API field names.
| Type | Default |
|---|---|
?string | null (uses property name) |
#[Field(mapTo: 'positions.id', group: 'criteria')]
public int $position_id; // In group(): key will be 'positions.id'INFO
mapTo only affects the output key in group(). It does not affect toArray(), which always uses the property name.
See Field Grouping for details.
preProcess
Function or class to transform value before validation.
| Type | Default |
|---|---|
?string | null |
Accepts:
- Global function name:
'trim','strtolower' - Class implementing
ProcessorInterface - Class implementing
CasterInterface - Static method name on the Request class
#[Field(preProcess: 'trim', rules: 'required|string')]
public string $name;
#[Field(preProcess: HtmlSanitizer::class)]
public string $content;See Processors for details.
postProcess
Function or class to transform value after validation and casting.
| Type | Default |
|---|---|
?string | null |
WARNING
When postProcess is defined, automatic type casting is skipped. The postProcessor must return the correctly typed value.
#[Field(rules: 'required|string', postProcess: 'strtolower')]
public string $email;
#[Field(postProcess: JsonDecoder::class)]
public array $metadata;See Processors for details.
group
Assign field to a named group for bulk extraction.
| Type | Default |
|---|---|
?string | null |
#[Field(group: 'filters')]
public ?string $search = null;
#[Field(group: 'filters')]
public ?string $status = null;
// Extract all filter fields
$filters = $dto->group('filters');See Field Grouping for details.
generator
Class to auto-generate field value. Must implement GeneratorInterface.
| Type | Default |
|---|---|
?string | null |
#[Field(generator: UuidGenerator::class)]
public string $id;Behavior:
- Request value is ignored — always generates new value
- Field bypasses validation rules
- Runs before casting
See Generators for details.
generatorOptions
Options array passed to generator's generate() method.
| Type | Default |
|---|---|
array | [] |
#[Field(
generator: SequenceGenerator::class,
generatorOptions: ['table' => 'orders', 'prefix' => 'ORD']
)]
public string $orderNumber;exclude
Exclude field from toArray() output.
| Type | Default |
|---|---|
bool | false |
#[Field(rules: 'in:pending,processing', exclude: true)]
public string $internalStatus = 'pending';
$dto->toArray(); // Does NOT include 'internalStatus'
$dto->internalStatus; // Still accessible directlyitems
Request class for validating and processing nested array items. Must extend Request.
| Type | Default |
|---|---|
?string | null |
#[Field(rules: 'required|array|min:1', items: OrderItemRequest::class)]
public ?array $items = null;Behavior:
- Each array element goes through the referenced Request's full pipeline
- Auto-casting is skipped on the parent field
- Validation errors use dot-notation:
items.0.field - Cannot be combined with
generator
See Nested Items for details.
Optional Attribute
The #[Field] attribute is optional. Properties without it are still processed:
final class UserRequest extends Request
{
#[Field(rules: 'required|string')]
public string $name; // With validation
public ?string $email = null; // No validation, just populated
public int $page = 1; // No validation, has default
}Complete Example
final class CreateOrderRequest extends Request
{
#[Field(generator: UuidGenerator::class)]
public string $id;
#[Field(
rules: 'required|integer|exists:users,id',
mapFrom: 'customer.id'
)]
public int $customerId;
#[Field(rules: 'required|array|min:1', items: OrderItemRequest::class)]
public ?array $items = null;
#[Field(
rules: 'nullable|string|max:500',
preProcess: 'trim'
)]
public ?string $notes = null;
#[Field(
rules: 'in:pending,confirmed',
exclude: true
)]
public string $status = 'pending';
#[Field(
cast: 'datetime:Y-m-d',
group: 'meta'
)]
public ?DateTime $deliveryDate = null;
#[Field(group: 'meta')]
public ?string $couponCode = null;
}Configuration Validation
Invalid configurations throw ConfigurationException at build time:
| Error | Cause | Fix |
|---|---|---|
| Nullable rule with non-nullable type | #[Field(rules: 'nullable')] on string | Use ?string |
| Required with default | #[Field(rules: 'required')] on = 'default' | Remove default or required |
| Incompatible cast | #[Field(cast: 'string')] on int | Match cast to property type |
| Invalid processor | Non-existent function/class | Check spelling, implement interface |
| Invalid generator | Class doesn't implement GeneratorInterface | Implement the interface |
| Invalid items class | Class doesn't exist or doesn't extend Request | Check class name, extend Request |
| Items requires array type | items on non-array property | Use array or ?array type |
| Items with generator | Both items and generator set | Remove one — mutually exclusive |
| Invalid items class | Class doesn't exist or doesn't extend Request | Check class, extend Request |
| Items requires array type | items on non-array property | Use array or ?array type |
| Items with generator | Both items and generator set | Remove one — mutually exclusive |