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

Eav Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is a Symfony bundle, not a Laravel package. It ships Doctrine ORM entities, a DI extension, form types, and event subscribers. With 10 stars, zero dependents, and a last release of 2016-01-13, composer require opifer/eav-bundle will not resolve on any modern Laravel/PHP 8 stack (it pins Symfony 2.3/3.0-era constraints and PHP 5.x idioms). Treat it as a reference implementation of the EAV pattern and a source of copyable code (MIT), not a dependency.

If you're evaluating it, read in this order:

  1. Model/AttributeInterface.php + Entity/Attribute.php — the schema: name, slug, type/storage type, options, required, group.
  2. Model/ValueSetInterface.php + Entity/ValueSet.php — the bag that holds one entity's values.
  3. Entity/AttributeValue.php — the actual EAV row: value_set_id, attribute_id, plus typed columns (string_value, text_value, integer_value, boolean_value, datetime_value).
  4. AttributeType/* — the strategy layer deciding storage column, form type, and constraints per type.
  5. DependencyInjection/ — service tags and opifer_eav.classes.* overrides.

First use case: a product catalog where the long tail of specs (color, weight, material, compliance flags, per-category extras) would otherwise mean a migration per attribute. Attach one ValueSet to the product; each spec becomes an AttributeValue. The pattern pays off exactly there and nowhere else.

Implementation Patterns

  • ValueSet per entity, never entity_id on the value row. Keep a value_sets table and a nullable value_set_id FK on your model. This is the bundle's core design and it's correct — it makes cloning an entity a clone of the ValueSet and makes partial saves coherent.
  • One strategy class per attribute type. Mirror AttributeTypeInterface: a class exposing storageType(), formType(), validationRules(), cast($value). In Laravel, back it with a registry (tagged services or a config/eav.php map) resolved through a small EavManager.
  • Shared schemas. Group attributes into AttributeGroups (a template) attached to a category; a new product inherits a ValueSet seeded from the group. This is what makes EAV usable by admins instead of painful.
  • Hydration layer. Write an AttributeBag that maps valueSet.values into slug => value with get($slug, $default) and back into rows on save. Controllers should never touch AttributeValue directly.
  • Read path. Eager-load valueSet.values.attribute in a single query and cache the attribute definitions (they rarely change). Never build a multi-join query to filter on an EAV field.
  • Write path. In a transaction: ensure ValueSet exists → diff incoming by attribute_id → insert/update/delete only the delta. This is the single biggest correctness win and the most common place reimplementations get it wrong.
  • Hybrid model. Keep real columns for the 5 attributes you sort/filter on and sync them from the EAV layer via model events. EAV for the long tail, columns for the hot path.
  • Laravel bridge. Realistically it's ~300 lines: three Eloquent models, a HasEav trait, a type registry. Faster and safer than dragging in a dead Symfony bundle through a Doctrine shim.

Gotchas and Tips

  • It will not install. Expect to fork and strip DependencyInjection, Resources/config, and the form types. Budget for that or skip it.
  • No uniqueness enforcement. Nothing prevents two AttributeValue rows for the same (value_set_id, attribute_id). Add a unique index and enforce it in the repository — the bundle leans on the form layer.
  • Storage columns are not typed. Values land in whichever column getStorageType() names. Changing an attribute's type later orphans old data — always migrate values, never just flip the type.
  • Cascade deletes. Deleting a parent entity must delete its ValueSet and values. Be explicit with onDelete('cascade'); ghost rows accumulate silently otherwise.
  • Never hard-delete an attribute in use. Soft-delete and filter on read, or historical entities lose fields with no trace.
  • Option lists are a trap. SelectType/MultiSelectType options are entities; deleting or reordering an option referenced by existing values corrupts meaning. Block delete when referenced, store a stable key.
  • Debugging "missing field". Always check the same three things: (1) attribute attached to the group, (2) value_set_id actually set on the entity, (3) the row's populated typed column matches the attribute's storage type. That's ~90% of EAV bugs.
  • Extension point worth copying. In the Symfony code, custom types register as services tagged opifer.eav.attribute_type; opifer_eav.classes.* swaps entity classes (any override must still satisfy the interface or Doctrine mappings break). Port the tagged-registry idea, not the YAML.
  • Performance ceiling. EAV is an authoring/reporting pattern. If you're sorting a listing on an EAV field, stop and promote it to a column.
  • Don't depend on it. Archived, 10 stars, 0 dependents, no maintainer since 2016. Cite it in your ADR as a reference design and ship your own three tables.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource