Skip to content

v3.0.0

Choose a tag to compare

@SoloPHP SoloPHP released this 26 May 09:10
· 4 commits to main since this release

Composable attribute API with explicit source bags

A ground-up redesign. #[Field] is split into focused per-concern attributes, route/context get their own bags instead of being merged into the body, and every misconfiguration is caught at metadata-build time.

Breaking release — every DTO needs to be migrated.

Highlights

  • 13 single-purpose attributes replace #[Field]: #[Validate], #[Cast], #[Caster], #[PreProcess], #[PostProcess], #[Generator], #[Items], #[Group], #[Exclude], #[Ignore], plus source attributes #[FromRoute], #[FromContext],
    #[FromBody] (dot-path).
  • handle() → handleBody() / handleQuery(); $routeParams becomes named $route + $context. No more silent merge into the body bag.
  • ProcessorInterface::process() now receives a ProcessContext DTO ($config, $route, $context) instead of raw arrays.
  • Structured validation errors: ['field' => [['rule' => 'X', 'params' => [...]], …]] instead of strings.
  • Nested #[Items] populates the array with instances of the items Request class (was: raw arrays).
  • Fail-fast metadata — 18 ConfigurationException factories surface DTO misuse at build time, naming the offending Class::$property.
  • 100% test coverage (213 tests), PHPStan level 8 clean.

Attribute migration

2.x 3.0
#[Field(rules: 'X')] #[Validate('X')]
#[Field(mapFrom: 'a.b')] #[FromBody('a.b')]
#[Field(cast: 'int')] #[Cast('int')]
#[Field(cast: MyCaster::class)] #[Caster(MyCaster::class)]
#[Field(preProcess: X)] #[PreProcess(X)]
#[Field(postProcess: X, postProcessConfig: […])] #[PostProcess(X, config: […])]
#[Field(generator: G, generatorOptions: […])] #[Generator(G, options: […])]
#[Field(items: I)] #[Items(I)]
#[Field(group: 'g', mapTo: 'k')] #[Group('g', mapTo: 'k')]
#[Field(exclude: true)] #[Exclude]

Other breaking changes

  • Every public non-static property is now managed. For controller-injected state, mark #[Ignore] or use protected/private visibility.
  • Route params are no longer merged into body — declare them with #[FromRoute].
  • 2.x silent paths now throw ConfigurationException: #[Cast(SomeClass)], #[Cast('unknown')], #[Cast]+#[Caster], #[Generator]+companions, #[Items]+#[Cast]/#[Caster], two source attributes on one property, non-static processor methods,
    empty-string attribute args.

Requirements

PHP 8.2+, PSR-7 HTTP Message. Recommended validator: solophp/validator.

Full Changelog: v2.2.0...v3.0.0