opifer/eav-bundle
Opifer EAV Bundle brings Entity-Attribute-Value modeling to Symfony and Doctrine apps, letting you attach dynamic, configurable attributes to entities without changing their schema. Define attributes, store values, and manage flexible data.
Architecture fit: poor — the framing error still needs correcting first. opifer/eav-bundle is a Symfony bundle, not a Laravel package. It does not participate in Laravel's service container, package discovery, facades, or Eloquent. Its integration surface is Symfony's Bundle/DependencyInjection lifecycle plus Doctrine ORM mappings. Adopting it inside a Laravel application means running a second ORM and a second persistence paradigm alongside Eloquent — an architectural commitment far larger than the feature itself. Release 0.2.5 does not touch any of this.
What changed in 0.2.5 — and why it matters more than the diff size suggests.
| Change | Reading |
|---|---|
Removed QueryValue |
A breaking API removal on a 0.x line. QueryValue was one of the few pieces addressing cross-attribute querying — the hardest part of EAV. Removing it narrows the bundle's query surface and invalidates any prototype written against 0.2.4. |
Added required to Attribute |
A schema-affecting feature: new persisted field, migration for existing attribute tables, default-value semantics for existing rows, and corresponding validation/admin-UI work. Small, but it confirms the attribute model is still evolving. |
Two changes, one breaking, in a patch-level bump, with no upgrade guide in the notes. That is the whole story: the package is not frozen, but is also not supported — the least convenient combination for a production dependency.
Upstream status is now contradictory and must be re-verified. The prior assessment recorded the repository as archived with a last release of 2016-01-13. A 0.2.5 publication contradicts that. Provenance matters: is this the original repository being revived, a maintained fork, or a re-tag? Until that is confirmed, treat "archived, 10 years stale" as unverified rather than established, and treat "actively maintained" as equally unverified. Neither claim should appear in a decision document without a link to the release and the maintainer's identity.
Integration feasibility: still low.
| Dimension | Finding |
|---|---|
| Framework lock-in | Symfony 2.x/early-3.x bundle API; no Laravel bridge exists |
| ORM lock-in | Doctrine ORM ~2.4-era; incompatible with Eloquent models |
| PHP compatibility | PHP 5.5–7.0 era; will not resolve on PHP 8.1+ without patching — unchanged by 0.2.5 |
| Composer resolution | Constraint conflicts remain near-certain against Laravel 10/11 dependency trees |
| Upstream support | 0.2.5 published; maintainer, cadence, and provenance unknown; no upgrade notes |
| Adoption signal | 10 stars, 0 dependents — effectively unexercised in production |
| Versioning contract | Pre-1.0; breaking changes permitted on any minor/patch. 0.2.5 proves it |
| License | MIT — forkable, still the only thing working in our favour |
Technical risk. The dominant risk remains escalation: an effectively unexercised package has no community pressure-testing, no CVE response path, and no compatibility patches. Release 0.2.5 adds a second risk rather than retiring the first — a moving target. Previously the code was frozen, which is bad for security but at least stable; now it can change under us without a support commitment, an upgrade guide, or a deprecation window. For a component we would have to fork anyway, churn is pure cost. Secondary risks are the standard EAV trade-offs — query complexity, type-coercion ambiguity, and referential integrity the database cannot enforce — none of which 0.2.5 addresses.
Key questions to resolve before any code is written.
casts cover most "custom fields per record" requirements without a pivot-per-attribute model.QueryValue, one of the few abstractions aimed at that problem. Confirm what, if anything, replaces it.required? Is there a migration, a default for existing rows, and validation enforcement downstream, or is it a column with undefined semantics for legacy data?required just added a field to it.Recommendation: unchanged — do not adopt opifer/eav-bundle as a dependency. 0.2.5 is a small, breaking release with no supporting documentation, and it does not touch the framework, ORM, or PHP-version barriers that disqualify the package for a Laravel application. It is a reference design, not a component: study the attribute/value modelling and typed-value handling at a pinned tag, then implement natively on Eloquent — or, preferably, avoid the pattern. "Zero dependents, no named maintainer, pre-1.0 with breaking patch releases" remains disqualifying for anything on a production path.
Stack fit: none, in the literal sense. There is no supported path from this bundle into a Laravel application, and 0.2.5 does not create one. The realistic options, in descending order of preference:
metadata JSON/JSONB column, a schema registry in application code, Laravel casts, and database-native JSON path indexes (MySQL 8 functional indexes, Postgres GIN). Delivers most of the flexibility at a fraction of the operational cost. Default recommendation.attributes, attribute_sets, attribute_values with explicit typed columns and a repository layer. Bounded scope — a few weeks — fully owned. Model required as a first-class column from day one; 0.2.5's addition is a useful requirement signal even if the implementation is not.QueryValue used to do, and carry maintenance permanently. Pin the fork baseline to a specific tag — do not track upstream, because upstream now changes.What 0.2.5 changes about the integration plan. Two concrete items:
QueryValue removal. Any spike or prototype that leaned on it is now invalid. If the discovery spike is evaluating the bundle as prior art, capture the 0.2.4 source for the query layer and document what it did before it disappeared.required on Attribute. Treat this as a requirement, not a feature: the clean-room or JSON design must carry per-attribute required-ness, enforce it at validation time, and define behaviour for records written before the attribute existed. Cheap to design in now, expensive to retrofit.Migration path. Extract the bundle as a reference specification, not a dependency: enumerate its entity model, type system, required semantics, and admin workflows; reimplement behind a repository interface. Vendor nothing you do not own, and cite the tag you read.
Compatibility work required, if forking. Doctrine DBAL/ORM major upgrades, Symfony Bundle API migration, PSR-11 container rewiring, nullable/typed-property fixes for PHP 8, reimplementation of the removed query abstraction, and a migration for the required column. A multi-week port, not a patch.
Sequencing.
| Phase | Duration | Exit criterion |
|---|---|---|
| Discovery spike | 1 week | Documented answer to "do we need EAV?" with query-pattern evidence; 0.2.5 provenance and maintainer status verified |
| Decision | — | Written build-vs-JSON-vs-fork recommendation signed off, naming the pinned tag studied |
| Bounded prototype | 2–3 weeks | JSON approach or native EAV proven against the three hardest real queries, including required-field validation |
| Hardening | 2 weeks | Index strategy, backfill, admin surface |
| Cutover | 1 week | Dual-write + read-shadow, then flip |
Non-negotiable design constraint. The persistence choice must sit behind an internal repository/query interface. EAV is expensive to reverse once attribute data is written; the abstraction is the only cheap insurance available — and it is also what protects us from upstream changes like 0.2.5.
Maintenance: we own 100% of it either way. If 0.2.5 signals a revival, we would be tracking a pre-1.0 component with breaking releases and no stated support model, no upgrade guide, and no LTS. If it is a one-off tag, we are back to owning an abandoned component. Neither branch produces a supported dependency. Any fork must be pinned, published to a private Composer registry, and staffed by a named owning team with a documented upgrade cadence.
Support: none established. No maintainer is named in the release notes, no upgrade guidance accompanies a breaking removal, and issue-triage behaviour is unknown. Internal knowledge will concentrate in whoever performs the port — a textbook bus-factor risk.
Scaling. Unchanged by the release: the value table grows as entities × attributes, and every cross-attribute filter adds a join. Expect to need composite indexes on (attribute_id, entity_id, value), typed value columns to avoid string-cast comparisons, and a denormalised read model (materialised view or search index) once attribute filtering reaches the critical path. Removing QueryValue makes the query layer more our problem, not less. Write amplification on entity save remains real and often underestimated.
Failure modes to plan for.
required — existing attribute rows have undefined required-ness; validation and UI can disagree about which fields are mandatory.Ramp-up. High and asymmetric. A new engineer needs Doctrine ORM, Symfony bundle internals, the EAV data model, and the fork's idiosyncrasies — four layers before they can fix a bug in a custom field. Add a fifth now: knowing which upstream tag we pinned and why. Contrast with JSON columns: one layer, already documented, and every Laravel developer on the market knows it.
Bottom line for the roadmap. 0.2.5 does not rehabilitate the package; it converts a stale dependency into a moving, unsupported one. The opportunity is real — flexible attribute systems are underserved in the PHP ecosystem — but this is not the vehicle. Budget the discovery spike, add a provenance check to it, expect it to conclude "JSON columns," and keep the EAV model — including required semantics — in the design notes as prior art. If the spike concludes otherwise, fund a clean-room build; do not fund a resurrection.
How can I help you explore Laravel packages today?