API Reference: Intro
All infrastructure that the concrete DTOs depend on — without this, no DTO compiles.
DTOInterface defines the contract every DTO must fulfill: fromArray(array): static, toArray(): array, id(): ?int, plus JsonSerializable so DTOs work with json_encode(). It carries a @template annotation for static analysis.
Cast provides type-safe coercion from API response data. Instead of every DTO calling (bool) $data['active'] (which turns "false" into true), Cast::boolOrNull() handles string-to-bool conversion correctly. Same for dateTime() (ISO 8601 → DateTimeImmutable), string() (with default), and intOrNull(). One file, tested once, used everywhere.
HasTimestamps trait supplies $created_at / $updated_at properties (both ?DateTimeImmutable, default null) and two static helpers: createdAt(array $data) and updatedAt(array $data) that call Cast::dateTime() internally. Eight of nine DTOs use this — TagDTO is the only exception since Zammad tags don't carry timestamps. Eliminates 16 identical lines across the codebase.
DtoHydrator offers a reflection-based alternative to manual fromArray(). It caches property metadata per DTO class and hydrates via constructor parameter reflection — no more hand-mapping 10+ fields per DTO. HydratesFromArray and SerializesToArray traits provide default implementations a DTO can use if it wants to skip writing fromArray() and toArray() manually.
Acceptance Criteria
Depends on
Produces
DTOInterface
Cast
HasTimestamps
DtoHydrator
HydratesFromArray
SerializesToArray
API Reference: Intro
All infrastructure that the concrete DTOs depend on — without this, no DTO compiles.
DTOInterfacedefines the contract every DTO must fulfill:fromArray(array): static,toArray(): array,id(): ?int, plusJsonSerializableso DTOs work withjson_encode(). It carries a@templateannotation for static analysis.Castprovides type-safe coercion from API response data. Instead of every DTO calling(bool) $data['active'](which turns"false"intotrue),Cast::boolOrNull()handles string-to-bool conversion correctly. Same fordateTime()(ISO 8601 → DateTimeImmutable),string()(with default), andintOrNull(). One file, tested once, used everywhere.HasTimestampstrait supplies$created_at/$updated_atproperties (both?DateTimeImmutable, defaultnull) and two static helpers:createdAt(array $data)andupdatedAt(array $data)that callCast::dateTime()internally. Eight of nine DTOs use this — TagDTO is the only exception since Zammad tags don't carry timestamps. Eliminates 16 identical lines across the codebase.DtoHydratoroffers a reflection-based alternative to manualfromArray(). It caches property metadata per DTO class and hydrates via constructor parameter reflection — no more hand-mapping 10+ fields per DTO.HydratesFromArrayandSerializesToArraytraits provide default implementations a DTO canuseif it wants to skip writingfromArray()andtoArray()manually.Acceptance Criteria
Depends on
Produces
DTOInterfaceCastHasTimestampsDtoHydratorHydratesFromArraySerializesToArray