Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Value Objects Laravel Package

michael-rubel/laravel-value-objects

Laravel Value Objects offers an abstract base class and Eloquent casts for turning model attributes into immutable value objects, with validation, comparison helpers, and PHP 8 support for cleaner, type-safe domain code.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Release assessed: 7.0.2 — patch-level; two PRs (PHP 8.4 CI coverage; negative-number fix in the Number value object), one first-time contributor. No breaking changes, no new features, no deprecations. Net effect on the prior assessment: one named risk is reduced (runtime/version matrix), one caution is added (arithmetic semantics in Number were wrong and untested until now), and the recommendation is unchanged.

Architecture fit

  • Laravel-native utility library, not a framework: it provides immutable scalar wrappers (email, phone, name-style values) that slot into the domain/edge layers of an existing Laravel app without imposing structure. Low architectural commitment — the main attraction for a TPM is that it is swappable.
  • Fits cleanly at three seams we already own: FormRequest/validation boundary, Eloquent attribute casting, and typed parameters on action/service classes. Adoption can be incremental and reversible.
  • It does not replace DTOs, spatie/laravel-data, or enum-based domain modelling; treat it as a normalization + validation primitive, not a domain layer.
  • 7.0.2 does not add classes or change the catalogue, so the "which value objects do we actually need" scoping question is unchanged — and still the primary cost driver.

Integration feasibility

  • composer require with package auto-discovery; no infrastructure, no migrations, no config publishing required for baseline use. Estimated spike effort: 1–2 engineer-days for a POC, 1 sprint for a bounded production slice.
  • Real integration work is not the install — it is deciding the canonical form of each value (case-folding of emails, E.164 phone normalization, trimming) and confirming it matches what is already in the database and in API contracts.
  • 7.0.2 is a drop-in upgrade from 7.0.1; pin ^7.0.2 in the spike and expect no migration work. The negative-number fix is a behavior change only for callers that were relying on incorrect arithmetic in Number — we have no such callers today, so this is a clean adoption point.

Technical risk

  • Bus factor / sustainability: single-maintainer package from a prolific author. High output across many packages is a positive signal for competence and a negative signal for per-package long-term attention. 7.0.2 shows an outside contributor's PR merged and credited — a mild positive for triage responsiveness and community pull, but it does not change the underlying concentration.
  • Thin production evidence: 205 stars and 0 dependents means near-zero public battle-testing. We would be an early adopter, not a follower.
  • Behavioral coupling: validation failure semantics (thrown exception vs. boolean) determine whether a bad input becomes a 422 or a 500. This must be verified before any write path is wired up.
  • Persistence fidelity: normalization changes stored bytes. Legacy rows that fail the new cast, and columns sized for unnormalized input, are the two most likely production incidents.
  • Serialization surface: queue payloads, JSON resources, and cache keys all need a defined representation; undocumented JsonSerializable behavior is a common source of subtle breakage.
  • Version matrix risk (reduced): 7.0.2 explicitly tests against PHP 8.4, so the forward-runtime story is better than assumed — but the release notes evidence only the PHP matrix. Laravel 11/12 support must still be confirmed from composer.json constraints, which this release does not demonstrate.
  • Edge-case correctness in Number (new): a sign-handling bug in a scalar wrapper is the kind of defect that surfaces as an off-by-a-minus in an invoice, refund, or ledger delta. That it shipped in 7.0.1 and needed a community fix tells us the test suite did not cover signed inputs. Treat any arithmetic-bearing value object as unverified and assert our own expectations rather than trusting upstream green builds.

Key questions

  1. Which value objects in the catalogue do we actually need, and which are decorative? A 5-class subset is supportable; a 20-class dependency is not. Number should be excluded unless a concrete use case requires it.
  2. What is the exact failure mode on invalid input, and can we map it to a 422 at the HTTP boundary and a domain exception internally?
  3. Does the cast handle null, empty string, and dirty legacy data gracefully, or does it throw on read?
  4. What are the declared composer.json constraints? PHP 8.4 is now CI-verified; is Laravel 11/12 in the constraint set, and is there a documented semver/BC policy?
  5. Is the repository actively triaged (issues/PR latency in the last 6 months), independent of the last tagged release date? 7.0.2 is one data point in favor.
  6. Do we need the cast integration at all, or would standalone instantiation at the request boundary give us 80% of the value with 20% of the coupling?
  7. (new) If Number is in scope, are signed values, zero, and precision/rounding covered by our own tests?

Integration Approach

Stack fit

  • Composes with, rather than competes against, our existing stack: native Eloquent casts, FormRequest rules, and API Resources remain the integration points. No conflict with spatie/laravel-data-style DTOs if we keep value objects at the leaf positions.
  • Best fit is a Laravel app with a service/action layer already in place; poorest fit is a codebase still doing validation inline in controllers, where the package would add a second convention alongside the first.

Migration path

  • Do not retrofit the whole model layer. Adopt at the boundary first: request → value object → persist, on a single bounded context.
  • Introduce an internal namespace/alias (e.g., App\Support\ValueObjects) that wraps or extends the package classes. This gives us a one-file swap if the package is abandoned, and a place to centralize our normalization rules.
  • Keep the database representation explicit: store the normalized string, and add a *_normalized or documented canonical form before changing existing columns.

Compatibility

  • Verify the package's Laravel/PHP constraints against both the current runtime and the next planned upgrade; a mismatch here is the single most likely reason to reject the dependency. PHP 8.4 is now evidenced by CI; Laravel 11/12 is not evidenced by this release and remains to be read from composer.json.
  • Audit for collisions with existing custom casts and accessors/mutators on the same attributes — Laravel will silently prefer one, and it is rarely the one you want.
  • Freeze the external contract: JSON shape, sort/filter behavior, and search semantics must not change when normalization is introduced.

Sequencing

  1. Spike (1–2 days): install ^7.0.2 in a sandbox branch, exercise each candidate value object, record failure modes and serialization behavior. Include signed/zero inputs if Number survives scoping.
  2. Inventory: list candidate attributes across models, flagging which have legacy dirty data and which are externally exposed.
  3. Pilot: one bounded context — typically user profile fields (email, phone, name) — with full test coverage and a static-analysis pass.
  4. Backfill audit: query for rows that would fail the new cast before enabling it on production reads.
  5. Expand: roll out domain by domain, gated on the pilot's incident count being zero for a defined soak period.
  6. Document: internal convention doc and a decision record naming an owner and a review date. Note the 7.0.2 baseline explicitly so the fork contingency starts from a known-good tag.

Operational Impact

Maintenance

  • Code footprint is small, so direct maintenance cost is low; the real carrying cost is dependency governance — periodic review of upstream activity, constraint compatibility with each Laravel upgrade, and a standing fork-if-abandoned contingency.
  • Recommend an explicit fork policy up front (who forks, where it lives, how it is published) rather than negotiating it during an incident.
  • The 7.0.2 patch cadence is normal and low-drama; budget a routine monthly composer outdated review rather than continuous tracking.

Support

  • Community-only: GitHub issues, no SLA, no commercial backing. We are the support tier.
  • Mitigate with a named internal owner, an internal README covering our canonical forms and exception mapping, and tests that assert our expected behavior rather than the package's. The Number fix reinforces this: upstream green is not our green.

Scaling

  • Runtime overhead is negligible at request scale: one validation pass per instantiation.
  • It is not free in hot paths — bulk imports, seeders, and batch jobs constructing thousands of value objects per minute should validate once at the boundary and pass primitives internally, or benchmark before adopting in those loops.

Failure modes

  • Unmapped validation exceptions → 500s on malformed user input where a 422 was expected. Highest-frequency risk; fix with a global handler mapping before rollout.
  • Legacy dirty data → cast exceptions on read for records that predate normalization. Detect with an offline audit query; never discover this in production.
  • Column truncation → normalized values exceeding existing VARCHAR lengths (phone numbers gaining country codes is the classic case).
  • Silent behavioral drift → normalization changing equality, uniqueness, or search matching (e.g., duplicate-email checks against a mixed-case column).
  • Serialization breakage → queue jobs or cached payloads failing after a value object replaces a string in a DTO.
  • Arithmetic correctness drift (new) → a wrapper-level bug in a numeric type producing wrong values downstream of persistence, where the wrong value is durable and harder to detect than an exception.

Ramp-up

  • Small, discoverable API: a mid-level Laravel developer is productive in roughly half a day with the internal convention doc and two worked examples.
  • Budget additional review time for the pilot PR — the review burden is in the normalization decisions, not the code.
  • Add a short internal note on which upstream version we baseline and why, so reviewers can distinguish "upstream changed" from "we changed" when behavior shifts after a routine bump.

TPM recommendation: proceed to a timeboxed spike and a single-context pilot on 7.0.2; do not adopt as a cross-cutting standard until the exception-mapping, legacy-data audit, and upgrade-constraint questions are answered. 7.0.2 improves the dependency's risk profile slightly — PHP 8.4 is now CI-verified and an external contribution was triaged and merged — but it does not answer the Laravel-version, BC-policy, or legacy-data questions, and the Number defect is a reminder that correctness in edge cases lives with us. Exclude Number from the initial scope. The package's low coupling makes a reject-or-reverse decision cheap, which remains the main reason the risk is acceptable at all.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk