Skip to content

Releases: std-out/simple-data-objects

v1.18.0

Choose a tag to compare

@yuriizee yuriizee released this 30 Jul 08:41

[1.18.0] — 2026-07-30

Removed

  • Support for Laravel 10 and 11.
    • Both majors are past their security-support window.
    • Every laravel/framework release on either line — including the newest patch — is now flagged by Packagist's security-advisory database.
    • Composer 2.9+ refuses to install them at all (config.policy.advisories.block rejects the resolution outright).
    • This isn't a version bump we chose; dependency resolution for those majors is no longer possible.
  • Updated minimum requirements: Minimum supported range is now Laravel 12–13.
    • illuminate/contracts, illuminate/support, illuminate/validation, illuminate/console, illuminate/database, and illuminate/http all move to ^12.0|^13.0.

[1.17.0] — 2026-07-29

Added

  • SimpleDataObjectsServiceProvider — artisan commands and automatic controller injection.
    • Manual Registration: Not auto-discovered — register it yourself in bootstrap/providers.php. Every other Laravel-facing piece in this package is already opt-in per-class, and this is the one that adds process-wide container behavior, so turning it on is a deliberate step rather than something that changes behavior for every Laravel app that installs this package.
    • Automatic Injection & Validation: Type-hint a BaseData subclass that uses HasLaravelIntegration as a controller or route-closure parameter and it hydrates + validates from the current request automatically.
      • No FormRequest needed.
      • A validation failure still surfaces as the normal ValidationException422.
    • Zero Overhead: Implemented as a beforeResolving(BaseData::class, ...) container hook scoped to BaseData and its subclasses, so it adds no overhead to unrelated container resolutions. Classes without HasLaravelIntegration, already explicitly bound classes, and abstract base classes are all left alone.
    • Global Configuration: Opt out globally with inject_from_request => false in the new publishable config/simple-data-objects.php.
    • New Artisan Commands:
      • sdo:warm / sdo:clear: Thin wrappers over the existing CacheWarmer/MetadataRegistry, auto-registered against php artisan optimize.
      • make:data: A DTO stub generator.
        • --from-model: Reads a model's table columns (Schema::getColumns(), Laravel 11+) into typed constructor-promoted properties.
        • --rules: Adds inferred #[Rules].
        • --collection: Adds a doc-comment pointing at the existing static::collection().
    • Documentation: See Service Provider & Commands.

Full Changelog: v1.16.0...v1.18.0

v1.15.0

Choose a tag to compare

@yuriizee yuriizee released this 26 Jul 06:50

[1.15.0] — 2026-07-26

(решта секції ### Added уже на місці, без змін).

Для GitHub Release:

What's New

WireableData trait — Livewire integration

Data objects can now be used directly as public Livewire component properties:

use StdOut\SimpleDataObjects\Concerns\WireableData;                                                                                                                                                                               
                                                                                                                                                                                                                                  
class OrderData extends BaseData implements \Livewire\Wireable                                                                                                                                                                    
{                                                                                                                                                                                                                                 
    use WireableData;                                                                                                                                                                                                             
}                                                                                                                                                                                                                                 
  • toLivewire() / fromLivewire() delegate to the same toArray()/from() round trip as everywhere else — enum casts, DateTimeCast, and custom casts all apply consistently.
  • Zero footprint without Livewire: this package still has no dependency on livewire/livewire. The trait doesn't implement the interface itself (traits can't); your class adds implements \Livewire\Wireable, and that's
    the only place the dependency is needed.
  • Same decoupling pattern as HasLaravelIntegration — opt-in per class, no effect on plain-PHP or non-Laravel usage.

See the docs for details.

Full Changelog: v1.14.0...v1.15.0

v1.14.0

Choose a tag to compare

@yuriizee yuriizee released this 25 Jul 18:51

What's New

#[Discriminator] — polymorphic hydration for DTOs

Abstract data classes can now dispatch from() to the right concrete subclass based on a field value — the PHP equivalent of Rust serde's tagged enums or pydantic's discriminated unions:

#[Discriminator(field: 'type', map: [
    'card' => CardPaymentData::class,
    'bank' => BankPaymentData::class,
])]
abstract class PaymentMethodData extends BaseData {}

PaymentMethodData::from(['type' => 'card', ...]); // => CardPaymentData

v1.13.0

Choose a tag to compare

@yuriizee yuriizee released this 24 Jul 11:03

v1.13.0

Fixed:

  • Constructor-less classes previously dropped all hydration input silently instead of throwing or populating fields.

Added:

  • Constructor-less and hybrid DTOs — BaseData subclasses no longer require a constructor; plain typed properties and mixed constructor+property classes are both fully supported (all attributes, readonly properties, with(), fromLazy()).

v1.12.0

Choose a tag to compare

@yuriizee yuriizee released this 22 Jul 12:12

v1.12.0

Added

  • MoneyCast and ValueObjects\Money — a small immutable money value object (minor units + currency) instead of floats. Accepts int minor units, a decimal string, an ['amount' => ..., 'currency' => ...] array, or an existing Money on hydration; serializes back to int minor units. Currency is fixed per field via the cast constructor and validated on both directions; raw float input is rejected. Decimal-string parsing never goes through float, so amounts round deterministically regardless of binary float representation.

v1.11.0

Choose a tag to compare

@yuriizee yuriizee released this 15 Jul 18:16

CommaSeparatedCast — splits a delimited string into an array on
hydration and joins it back on serialization (separator and trim
are configurable; default , and true).

v1.10.0

Choose a tag to compare

@yuriizee yuriizee released this 15 Jul 16:22

UuidCast — validates RFC 4122 UUID strings on hydration and normalizes to lowercase on both hydration and serialization. Invalid input throws InvalidArgumentException.

v1.9.0

Choose a tag to compare

@yuriizee yuriizee released this 15 Jul 11:36

Added

  • LowercaseValuePipe / UppercaseValuePipe — case normalization pipes for #[Pipe]-attributed properties, e.g. emails or country/currency codes.
    Non-string values pass through untouched (same contract as TrimValuePipe).

Changed

  • Documentation site: custom VitePress theme with breadcrumb navigation.

Full Changelog: v1.8.0...v1.9.0

v1.8.0

Choose a tag to compare

@yuriizee yuriizee released this 03 Jul 12:06

Slimmer installs

📦 Changed

  • Dev-only files (tests, docs, CI config, Docker setup) are now excluded from Composer dist archives via .gitattributes export-ignore — composer require std-out/simple-data-objects downloads only what runs in production.

Full Changelog: v1.7.2...v1.8.0

v1.7.2

Choose a tag to compare

@yuriizee yuriizee released this 03 Jul 11:20

Universal from() + lazy hydration

✨ Added

  • Universal from() — one factory now accepts arrays (unchanged fast path), Eloquent models and any Arrayable, stdClass, JsonSerializable, any Traversable, JSON strings, plain objects with public properties, and same-class instances (returned as-is). All detection lives on the cold path — the hot array path executes the same opcodes as before.
  • BaseData::fromLazy() — lazy hydration built on native PHP 8.4 lazy ghosts; hydration runs on first property access. With ~10% of objects actually read: ~3× faster on cast-heavy DTOs, ~6× with nested collections.
  • Integrations docs — Plain PHP, Laravel, Symfony, Slim/PSR-7, plus an opcache.preload recipe.

⚡ Changed

  • Compiled hydrator hoisted out of collection loops (TypedDataCollection::of(), lazyCollection()): +19% on collection hydration (220k → 267k ops/s).
  • fromJson() is now an explicit alias of from().

🐛 Fixed

  • HydratorCompiler::compile() fails fast when given a non-BaseData class.

Full Changelog: v1.4.3...v1.7.2