plusforta/value-objects-bundle
A Laravel bundle of reusable value objects for common domain concepts, helping you keep validation, casting, and type safety consistent across your application instead of scattering raw strings and primitives throughout your models and services.
Architecture fit. plusforta/value-objects-bundle is a leaf-type library: immutable, self-validating value objects for strings, numbers, booleans, collections, and equality/comparison helpers, plus Symfony/PHP framework configuration. For a TPM this matters because the blast radius is small — value objects hold no I/O, no state, and no framework coupling beyond the cast/serialization layer, so the dependency is easy to reason about, easy to wrap, and easy to remove. The real question is not architectural fit but domain vocabulary fit: adopting this bundle means adopting someone else's decisions about what a valid IBAN, a money amount, or a normalized string looks like. That is a product decision as much as an engineering one.
Integration feasibility. Mechanically low-cost — Composer install, provider registration, config publish, casts on Eloquent attributes. The integration surface is narrow (casts, validation, serialization), so a spike is measured in hours to a week, not sprints. The limiting factor is confidence, not effort: zero stars, zero dependents, GitLab-hosted, no public issue history, no community-authored usage examples, and no visible changelog discipline. Feasibility is high; assurance is low until the source and tests are read.
Technical risk.
filter_var for email, libphonenumber-backed phones or not, DE/EU conventions for IBAN/BIC/VAT). Divergence from our policy forces forks or local overrides.illuminate/support.readonly/private constructors are enforced or merely conventional — PHP value objects frequently leak mutable internals (arrays, DateTime).moneyphp/money + brick/money carry years of edge-case coverage.Key questions.
Stack fit. Presumed Laravel 9/10/11, PHP 8.1+, Composer, Eloquent, with Symfony-style configuration. It introduces no new runtime — no extension, no daemon, no service — so it sits in the cheapest integration category. That is precisely why governance and domain risk, not engineering risk, should drive the decision. Confirm fit first: composer why-not plusforta/value-objects-bundle in a scratch project mirroring our composer.json, watching illuminate/support, illuminate/database, and the php constraint. A single-minor Laravel pin means point-in-time adoption and self-owned patches.
Migration path. Recommend the strangler/pilot, not big-bang:
App\Domain\ValueObjects\* as subclasses or delegating wrappers so application code depends on our namespace. Small ceremony, one-file-per-type exit ramp.For persistence, cast at the model boundary while keeping raw column representations (string/int) unchanged, so schema and JSON contracts are not coupled to the package's serialization choices.
Compatibility. Verify against our actual matrix before committing: PHP range, Laravel version support, illuminate/* constraints, and whether the bundle's Symfony configuration conflicts with existing service providers. Record the verified matrix in the ADR so future upgrades have a baseline.
Sequencing.
moneyphp/money.Maintenance. Vendored, this is our code: we own bug fixes, PHP/Laravel upgrades, and security patches. Budget a modest, recurring line item — realistically a few days per year plus upgrade-window work at each Laravel major. Un-vendored, maintenance is outside our control, which is unacceptable for types sitting in money and identity paths. Assign a named owner and record it in the ADR; unowned shared primitives decay into N divergent forks.
Support. No vendor support, no SLA, no public issue history to gauge responsiveness. Internal support means internal documentation: which types we adopted, which we deliberately excluded, and how to add a new one. Expect onboarding friction to be low for consumers (types are self-documenting, validation errors are explicit) and moderate for contributors (they must understand the immutability and equality contracts before extending).
Scaling. Runtime cost is negligible — these are plain PHP objects, and the casts add microseconds. The scaling concern is organizational: a shared value-object vocabulary is a shared kernel, and shared kernels need governance. Without a lightweight change process, one squad's stricter email validation becomes another squad's production incident. Define who may add types and how breaking changes to validation policy are communicated.
Failure modes.
DateTime) escaping an ostensibly immutable object; test for it explicitly.moneyphp/money and property-testing against known vectors.Ramp-up. Engineers need roughly a day to be productive with the base abstractions (construction, validation, equality, casting) and a week to be confident extending them or debugging serialization. TPM-facing ramp-up is the ADR plus a short "which primitive for which field" table so product and engineering converge on the same vocabulary — that table, more than the code, is what keeps squads consistent. Success criteria for the pilot: the same recurring defect classes from the last 6–12 months of the bug taxonomy become unrepresentable, and net validation code decreases. The rollback costs nothing more than deleting the fork.
How can I help you explore Laravel packages today?