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

Attribute Bundle Laravel Package

padam87/attribute-bundle

A Symfony bundle for adding flexible, configurable attributes to Doctrine entities without schema changes. Define attribute types, attach dynamic values to records, and query them through a simple, reusable API.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: padam87/attribute-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config publish, no facade. Treat it as a reference implementation of an "entity attributes" pattern rather than a drop-in dependency — the score (2.2) and the 2015 last release reflect that it will almost certainly conflict with modern Laravel/Symfony constraints if you composer require it directly.

If you are evaluating the pattern to port into Laravel:

  1. Read the source in this order: AttributeValueInterface → AttributeTrait → AttributeValue entity. That's the entire contract — a polymorphic key/value store attached to any model.
  2. Note the storage shape: one row per attribute per owner, with a name/value pair and an owner reference. This is EAV-lite.
  3. Sketch the Laravel equivalent: a morphMany relation from your model to an attribute_values table (attributable_type, attributable_id, name, value).

First use case: arbitrary per-record metadata you don't want as columns — product specs, CMS page settings, feature flags scoped to a tenant, custom fields captured from a form. Start with a single model and a single HasAttributes trait; do not generalize until you have two consumers.

Implementation Patterns

Trait-on-the-model (the core pattern). In Symfony the bundle expects you to use AttributeTrait on your entity and implement the interface. The Laravel port is the same idea:

trait HasAttributes
{
    public function attributes(): MorphMany
    {
        return $this->morphMany(AttributeValue::class, 'attributable');
    }

    public function setAttribute(string $name, $value): static
    {
        $this->attributes()->updateOrCreate(['name' => $name], ['value' => $value]);
        return $this;
    }
}

Accessor workflow. The original exposes getAttribute($name)/setAttribute($name, $value) style calls. Keep the read path cheap: eager-load attributes on list endpoints (->with('attributes')) and build a keyed array once, rather than hitting the relation per key. A small AttributeBag value object that hydrates from the loaded collection pays for itself quickly.

Form / request integration. The Symfony bundle ships form types for editing attributes. In Laravel, the equivalent is a repeatable field group (attributes[color], attributes[size]) validated against an allow-list of known attribute names per entity type. Store the allow-list in config, not the database, so validation stays declarative.

Querying. Don't try to whereHas for every filter — join the attributes table once for the filters you actually support, or denormalize the handful of searchable attributes into real columns. The bundle's generic storage gives you no index on value; plan for that.

Integration tip. If you retain any of the original PHP classes for reference, keep them out of app/ and out of the autoload path — put them under docs/ or a scratch namespace so Laravel's container and route model binding never pick them up.

Gotchas and Tips

  • It is not installable in a modern Laravel app without pain. The composer.json targets Symfony 2.x-era components and old Doctrine. Expect constraint conflicts; use --dry-run first if you're just curious.
  • No Laravel auto-discovery. No Illuminate\Support\ServiceProvider, no config/attribute.php. Anything you want from this package you write yourself.
  • EAV pitfalls carry over. Attribute values are stored as strings in the original; typed values (bool, int, JSON) come back as strings. Cast on read and document the cast per attribute, or you will chase "false" being truthy.
  • N+1 is the default failure mode. Every $model->getAttribute('x') that isn't backed by a loaded collection is a query. Load the relation eagerly, always.
  • value column length and collisions. The original schema uses a modest string column; long text, JSON blobs, and duplicate names per owner need explicit handling (unique index on attributable_type, attributable_id, name).
  • No cascade/cleanup guarantees. Deleting a parent model orphaned attribute rows in the original unless you wired it up; in Laravel add ->cascadeOnDelete() or a model deleting hook.
  • Extension point: the bundle expects you to subclass/replace the AttributeValue entity via Doctrine mapping overrides. In your Laravel port, that's simply your own model — take the opportunity to add a type column now rather than migrating later.
  • Debugging: if attributes "disappear," check the morph map (Relation::enforceMorphMap) and the attributable_type strings — class renames silently orphan rows.
  • Bottom line for assessment purposes: the value here is the interface and trait shape, not the code. Budget an afternoon to port the idea; budget a week to fight the dependency and lose. Copy the pattern, cite the MIT license, and move on.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core