Skip to content

Releases: SoloPHP/Input

v1.1.0

Choose a tag to compare

@SoloPHP SoloPHP released this 28 Oct 14:08
002c374

One meaning for an empty input: null, and a "" the field's type cannot hold, are no value. The factory reads such a "" as null before validation, the validator checks a null like a missing field — by presence rules alone — and the field holds null, keeps its default or reports required.

#[Validate('string|max:100')]
#[EmptyToNull]
public ?string $q = null,      // ?q=    → null (1.0: `string` error)

#[Validate('boolean')]
public ?bool $done = null,     // ?done= → null (1.0: `boolean` error)

#[Validate('integer|min_value:1')]
public int $page = 1,          // ?page= → 1    (1.0: `integer` error)

Fixes

  • #[EmptyToNull] gives what it documents for a field with rules: a blank string is null, the default or required, where it failed the field's first rule — string for a string the client sent.
  • A rule matching the type is harmless for no value, as documented: ?done= for a boolean ?bool is null.

Behavior changes

  • A nullable field takes null without nullable in its rules, so in a partial update a null clears it. Keep it from being cleared with filled: #[Validate('filled|string|max:255')] public ?string $name = null.
  • A field with a default keeps it for no value — in a partial update a null resets it; one with neither reports required instead of the first rule it failed.
  • A "" for an array or #[Items] field, or for a custom caster's array type, is no value instead of []. Only a [] the client sends is the empty list.
  • Rules of your own run on no value only as presence rules: #[Validate('accepted')] public bool $terms = false takes false for null — drop the default and write required|accepted.
  • A null in #[FromContext] is no value too; rules that read another field see null where they saw "".
  • Rule strings reach the validator verbatim; a nullable you write keeps working.

Requirements

  • solophp/contracts ^1.8, whose ValidatorInterface checks a missing or null field by presence rules alone and conflicts with solophp/validator below 4.2 — so solophp/validator 4.2 or a validator of your own that keeps the rule.

See the upgrade guide for a 1.0 / 1.1 table of each change, and the full diff.

v1.0.0

Choose a tag to compare

@SoloPHP SoloPHP released this 27 Oct 21:28
81114d1

First stable release of Solo Input (solophp/input): typed, validated input DTOs for PHP 8.3+. Mark a class #[Input], declare its fields in the constructor, and the factory reads them from the request, validates and casts the whole input, then calls the constructor.

The API is the one of v1.0.0-RC3, unchanged; two applications have run the release candidates in production.

What 1.0 covers

  • Plain final readonly input classes, built once through their constructor after the whole input is valid.
  • Per-field sources: body or query by factory method, #[FromRoute], #[FromContext], #[FromBody('a.b')].
  • Lossless type casting driven by the declared type, including dates, backed enums, custom casters and #[Cast('decimal')].
  • Every error at once in one ValidationException, keyed by the input path (customer.id, lines.0.qty).
  • Processing stages (#[Normalize], #[Caster], #[PostProcess], #[Generator]), nested inputs and #[Items] lists.
  • Partial updates: Inputs::provided(), Inputs::toArray($input, onlyProvided: true) and #[Input(partial: true)].
  • Field grouping and a JSON-serializable schema() of the input contract.

From now on the public API follows semantic versioning; see Versioning for what it covers.

Install

composer require solophp/input

See the documentation and the full diff since RC3.

v1.0.0-RC3

v1.0.0-RC3 Pre-release
Pre-release

Choose a tag to compare

@SoloPHP SoloPHP released this 26 Oct 08:59
b682a39

Third release candidate of Solo Input (solophp/input). It adds #[Input(partial: true)], which moving the first real application to the package called for: the body of a partial update declares itself, and Inputs::toArray() gives its change set without every update endpoint having to ask for it.

This is a prerelease: the 1.0 API is being validated in real applications before the stable 1.0.0 tag.

Changes since 1.0.0-RC2

  • #[Input(partial: true)] marks the body of a partial update. Inputs::toArray() without an onlyProvided argument then gives the fields the request supplied, so a default never overwrites what is stored; an absent field still reads as its default, and onlyProvided: false asks for every field. The flag comes from the nearest #[Input] of the class or its parents, nested DTOs follow the call they are in, and a partial DTO the factory did not build exports nothing. See Attributes → #[Input] and Inputs::toArray().
  • Inputs::toArray()'s $onlyProvided is ?bool with a null default; passing a bool works as before.

Install

composer require 'solophp/input:^1.0@RC'

See the documentation and the full diff since RC2.

v1.0.0-RC2

v1.0.0-RC2 Pre-release
Pre-release

Choose a tag to compare

@SoloPHP SoloPHP released this 26 Oct 07:29
f64ce31

Second release candidate of Solo Input (solophp/input). It adds the built-in cast #[Cast('decimal')], which moving the first real application to RC1 called for: a number for a DECIMAL column, bcmath or a decimal library, written in plain decimal notation instead of the exponent notation PHP gives a small float.

This is a prerelease: the 1.0 API is being validated in real applications before the stable 1.0.0 tag.

Changes since 1.0.0-RC1

  • #[Cast('decimal')] on a string (or untyped / mixed) property writes a number in plain decimal notation: 0.00001 and '1e-5' as '0.00001', where the string cast gives '1.0E-5'. An int or a numeric string keeps every digit it has, and a float gives its shortest round-trip digits, so 0.1 stays '0.1'. "" is no value, as for int and float. Input that is no number, or a number a float overflows to infinity or rounds to zero although it is not zero, fails numeric. The schema reports such a field with cast: 'decimal'. See Type Casting → Decimal.
  • A property typed with a class named like a built-in cast (json, decimal) fails metadata building with ConfigurationException, like any class no input can produce, instead of being cast as that type.

Install

composer require 'solophp/input:^1.0@RC'

See the documentation and the full diff since RC1.