Open source
Attributes for Laravel
composer require roundly-consulting/attributes-for-laravelOverview
Dynamic, typed key/value attributes for any Eloquent model. Add one trait and a model gains a queryable set of custom fields — color, rating, on_sale, published_at — stored in a single polymorphic table, so a new field never needs a migration. Values come back as their real PHP type, and optional definitions add validation — across attributes too — defaults, unique and required constraints, encryption at rest and an audit trail of who changed what. MIT-licensed and built only on Laravel plus three small Roundly packages — no third-party dependencies.
What you get
Typed values
Strings, integers, floats, booleans, arrays and datetimes round-trip as their real PHP type — no manual casting.
Fluent builder & sync
Stage several attributes with metadata, then save them alongside the rest or sync them to an exact set — all or nothing, in one transaction.
Query scopes
Filter and order owner models by attribute — equality, sets, ranges, presence, null checks and ordering.
Definitions & constraints
Register known attributes globally or per model with Laravel rules — cross-attribute ones too — defaults, a strict mode, required attributes and database-enforced unique values — per model type, per team or tenant, or global.
Facade, DI or actions
Attributes::for($model) for every read and write, an injectable AttributesManager or single-purpose actions — and Attributes::fake() records every write.
Encryption at rest
Mark an attribute encrypted and it is stored as Crypt ciphertext, decrypted transparently on read — unique constraints still apply.
Audit trail & events
Opt-in old→new revision history that can record who made each change, an API resource for it, and after-commit events on attach, detach and sync.
Documentation
Installation
Install via Composer, publish and run the publish-only migrations, optionally publish the config file, and upgrade to 2.1.
Configuration
Every config key and its default — model, table, key types, strict mode, pruning, history and its actor, whole-set validation, resources and definitions.
Database schema & model
The attributes and revisions tables, owner key types for UUID and ULID models, and swapping in your own Attribute model.
The HasAttributes trait
Add the HasAttributes trait and contract to any Eloquent model to give it typed, queryable attributes — plus the method reference.
The Attributes facade
Attributes::for($owner) for every read and write of one model, plus definitions, validation, pruning and a recording fake.
DI and actions
Skip the facade: inject AttributesManager for the same API without static calls, or call a single-purpose action directly.
Typed values
Values keep their real PHP type — strings, integers, floats, booleans, arrays and datetimes round-trip without manual casting.
Attaching attributes & metadata
Attach one or many typed attributes, add metadata to any of them, and replace metadata without touching the value.
The fluent builder
Stage several attributes with metadata, adjust the staged set, then save alongside existing attributes or sync to replace them.
Reading attributes
Read typed values, strings, models and metadata; use the attr() accessor or typed readers; export attributes as key/value maps.
Query scopes
Filter and order owner models by their attributes — equality, sets, ranges, presence, null checks and ordering.
Removing & syncing
Soft-delete or force-delete attributes, remove all but a keep-list, and sync a model’s attributes to an exact set.
Definitions & validation
Register known attributes with a type and Laravel validation rules, seed them from config, and opt into strict mode.
Cross-attribute validation
Validate an owner’s whole attribute set in one pass, so rules like gte:min_price or required_if:kind,physical see the other attributes.
Per-model schemas
Declare attribute definitions on the model itself — as a property or a method — merged over global definitions for that model only.
Unique, required & defaults
Enforce unique values per model type, per team or tenant, or globally; assert required attributes on demand and read defaults for unset ones.
Encrypted values
Mark a definition encrypted to store its value as Crypt ciphertext at rest and decrypt it transparently on read — for every type.
History & audit trail
Opt in to an old→new revision on every change, record who made it, read it per model or attribute, and render it for an API.
Events
React to attribute changes with AttributeAttached, AttributeDetached and AttributesSynced — for audit logs, re-indexing or syncing.
Artisan commands
List an owner’s attributes, prune old soft-deleted attributes, and inspect the package configuration with about.
Enums
AttributeType, UniqueScope and RevisionType — with option lists, labels, lookups and comparators from enums-for-laravel.
Exceptions
Every exception the package throws, when it is thrown and the context it carries — all extend AttributesException.
Testing
Record writes with Attributes::fake() and its assertions, test against real rows with RefreshDatabase, and seed with the factory.
Requirements
PHP 8.4+ and Laravel 13, plus three small Roundly packages that Composer installs automatically.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.