Skip to content

Releases: ReallifeKip/ImmutableBase

v4.3.0

19 Apr 03:58

Choose a tag to compare

Added

  • #[InputKeyTo(KeyCase::X)] — Input key case conversion. Apply at class level to remap all incoming array keys before hydration, or at property level to override for a specific property. Conversion splits on camelCase/PascalCase boundaries, underscores, hyphens, and whitespace, then rejoins in the target case.
  • #[OutputKeyTo(KeyCase::X)] — Output key case conversion. Apply at class level to remap all serialized keys during toArray(true) / toJson(true), or at property level to override for a specific property.
  • KeyCase enum — 8 naming conventions: Snake (nick_name), PascalSnake (Nick_Name), Macro (NICK_NAME), Camel (nickName), Pascal (NickName), Kebab (nick-name), CamelKebab (nick-Name), Train (Nick-Name).
  • InvalidKeyCaseException — Thrown at definition time when #[InputKeyTo] or #[OutputKeyTo] receives a value that is not a KeyCase enum instance (e.g. a plain string).

v4.2.2

14 Mar 11:20

Choose a tag to compare

Fixed

  • Mark DataTransferObject::__construct as final to prevent
    unintended override in subclasses, aligning implementation with
    original design intent
  • Fix @desc annotation handling in ib-writer Markdown mode output:
    replaced isset() check with strict empty string comparison,
    preventing blank description lines from being written

v4.2.1

12 Mar 11:55

Choose a tag to compare

Refactored

  • Internal Structure Optimization: Extracted typescript namespace rendering logic into a standalone renderNamespaces (formerly namespacesHandler) method to reduce cognitive complexity in contentGenerate.
  • Naming Alignment: Renamed internal methods to strictly follow the render* naming convention for better clarity and maintainability.
  • Control Flow Refactoring: Replaced several if-else blocks with match expressions to reduce Cyclomatic Complexity and align with Sonar quality standards.

Fixed

  • Sonar Compliance: Added explicit documentation and justifications for empty methods to resolve "Methods should not be empty" code smells.

v4.2.0

12 Mar 06:55

Choose a tag to compare

Added

  • Native enum — Primitive typed arrays via #[ArrayOf]. #[ArrayOf] now accepts Native::string, Native::int, Native::float, and Native::bool to declare arrays of validated PHP scalar values without wrapping them in a SingleValueObject.
  • ib-writer TypeScript output. vendor/bin/ib-writer now supports .ts generation, producing declare namespace blocks with interfaces for DTO/VO, type aliases for SVO, and enum/union types for referenced PHP enums.

Changed

  • Standalone null property type is now forbidden. Declaring a property typed as null alone throws InvalidPropertyTypeException at scan time. Use ?Type or Type|null for nullable properties.
  • InvalidPropertyTypeException message updated. Now explicitly lists allowed types and provides nullable usage guidance.
  • InvalidArrayOfItemException message updated. Now distinguishes between ImmutableBase class resolution failures and primitive type mismatches.

v4.1.2

07 Mar 14:21

Choose a tag to compare

Updated

  • Update the composer description and keywords

v4.1.1

07 Mar 06:50

Choose a tag to compare

Fixed

ib-writer

  • Property tables now include a default column displaying default
    values from #[Defaults] attributes and defaultValues() overrides
  • Enum types referenced as property types now generate their own
    documentation blocks with case listings and backing values
  • BackedEnum defaults display the backing value; UnitEnum defaults
    display the case name; dynamic defaults from defaultValues()
    display as (dynamic)

v4.1.0

06 Mar 17:50

Choose a tag to compare

Added

  • defaultValues() — Static default value declaration. Override defaultValues(): array to declare fallback values for properties absent from input data. Keys must match declared property names; unmatched keys are silently ignored. Supports any type valid for the target property, including subclasses of ImmutableBase and Enum.
  • #[Defaults(value)] — Attribute-based default value. Apply #[Defaults(value)] to individual properties for constant-expression defaults. Constrained by PHP attribute syntax to scalar values, arrays, and class constants.
  • Default value resolution priority. During construction (fromArray / fromJson), property values are resolved in the following order:
    1. Explicit input value (including explicit null)
    2. defaultValues()[$propertyName]
    3. #[Defaults(value)] attribute value
    4. null (if nullable) or RequiredValueException
  • Explicit null is respected. When a key is present in the input with a null value, it is treated as an intentional assignment — default values are not applied.
  • Cache-aware default values. ib-cacher serializes cacheable default values (scalars, arrays) into the cache file. Non-serializable defaults (objects, Closures) are excluded from the cache with a [Notice] warning and resolved at runtime via defaultValues() on every construction.
  • SVO defaultValues() sealed. SingleValueObject::defaultValues() is declared final and returns an empty array. SVOs require explicit values via from() by design.

Changed

  • __construct() uses array_key_exists() for default resolution. Replaces isset() to correctly distinguish between "key absent" (apply default) and "key present with null" (respect explicit null).

v4.0.0

01 Mar 17:46

Choose a tag to compare

The first stable release of v4 — a complete architectural overhaul from attribute-based annotations to inheritance-based object definitions.

Highlights:

  • extends DataTransferObject / ValueObject / SingleValueObject replaces #[DataTransferObject] / #[ValueObject]
  • New SingleValueObject type with TypeScript-like type narrowing
  • Automatic validation chain across inheritance hierarchy
  • with() deep path mutation with 44–68% performance improvement
  • CLI tools: ib-cacher (metadata cache) + ib-writer (doc generation)
  • Zero dependencies. Requires PHP 8.4+.

📦 composer require reallifekip/immutable-base


Breaking Changes

  • Architecture: Attribute annotation replaced by class inheritance. Objects are now defined by extending DataTransferObject, ValueObject, or SingleValueObject instead of annotating with #[DataTransferObject], #[ValueObject], or #[Entity].
  • Entity removed. The Entity object type has been removed entirely.
  • All properties must be public. In v3, ValueObject and Entity properties were private with getter methods. All properties now require public visibility, enforced at scan time. Classes should be declared as readonly class, which handles immutability at the PHP level.
  • Exception system rebuilt. All v3 exceptions have been removed and replaced with a structured hierarchy under ImmutableBaseException, categorized into LogicException > DefinitionException (design errors) and RuntimeException > InitializationException (input type violations) / ValidationException (domain constraint violations). See README for details.
  • object, iterable, and non-IB/non-Enum class types forbidden. Properties typed as object, iterable, or unsupported classes (e.g. DateTime, Closure) now throw InvalidPropertyTypeException at scan time.

Added

  • SingleValueObject (SVO). New object type for semantically meaningful single values. Provides from(), __toString(), __invoke(), and jsonSerialize(). Child classes can freely define the type of $value via interface + hooked property design.
  • equals(). Deep structural equality comparison for all ImmutableBase subclasses, with recursive comparison of nested objects and arrays.
  • #[Strict] / #[Lax]. Control whether undeclared input keys are rejected or accepted.
  • #[SkipOnNull] / #[KeepOnNull]. Control whether null-valued properties appear in toArray() / toJson() output.
  • #[Spec]. Attach a domain-specific validation message to VO/SVO, retrievable via ValidationChainException::getSpec().
  • #[ValidateFromSelf]. Reverse the validation chain direction to bottom-up (default is top-down).
  • Automatic validation chain. VO and SVO automatically traverse the entire inheritance hierarchy during construction. Each class in the chain is invoked if it defines validate(): bool, but defining it is optional -- classes without it are simply skipped without breaking the chain.
  • Hierarchical error path tracing. Nested construction errors include the full property path in the exception message (e.g. OrderDTO > $customer > $email > {error message}).
  • ImmutableBase::strict(). Global strict mode.
  • ImmutableBase::debug(). Debug logging for redundant input keys.
  • ImmutableBase::loadCache(). Load pre-generated metadata cache to bypass runtime reflection.
  • CLI: ib-cacher. Metadata cache generator. Supports --scan-dir for targeted scanning and --clear for cache removal.
  • CLI: ib-writer. Documentation generator producing Mermaid class diagrams and Markdown property tables.
  • Benchmark suite. Dedicated benchmarks for with() and hydration covering flat scalar updates, dot-notation deep paths, bracket notation, chained calls, and batch operations.

Changed

  • with() selective resolution. Only changed properties are resolved; unchanged properties are carried over by reference, yielding a 44–68% performance improvement depending on nesting depth.
  • with() deep path syntax now supports bracket notation (items[0].sku) and custom separators, in addition to existing dot notation.

Deprecated

  • #[DataTransferObject] attribute — use extends DataTransferObject.
  • #[ValueObject] attribute — use extends ValueObject.
  • #[Entity] attribute — removed entirely.

v3.1.3

14 Dec 13:22

Choose a tag to compare

  • Refactored core logic in src/ImmutableBase.php to introduce static caching for reflection properties and modes, enhancing performance for repeated operations.
  • Optimized walkProperties() method to cache property lists per class, significantly reducing reflection overhead on subsequent calls.
  • Enhanced property initialization by extracting logic into dedicated analyzeClass() method for better code organization and maintainability.
  • Improved toArray() implementation with new analyzeClassForToArray() callback method, providing cleaner separation of concerns.
  • Updated enum resolution with dedicated analyzeEnum() method, improving readability and error handling for enum value assignments.
  • Enhanced PHPDoc documentation and method descriptions throughout ImmutableBase.php for better developer experience and API clarity.

v3.1.2

24 Nov 13:47

Choose a tag to compare

  • Fixed a bug where Immutable Objects implementing a custom constructor skipped the normal initialization flow, causing toArray() to consistently throw errors. The initialization step is now guaranteed before property traversal, ensuring toArray() works correctly even with custom constructors.