NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

The published config/attributes.php in full, with the definition examples commented out:

return [
    'model' => RoundlyConsulting\Attributes\Models\Attribute::class,
    'table' => 'attributes',
    'key_type' => env('ATTRIBUTES_KEY_TYPE', 'bigint'),
    'strict' => env('ATTRIBUTES_STRICT', false),
    'prune_after_days' => env('ATTRIBUTES_PRUNE_AFTER_DAYS', 30),
    'history' => [
        'enabled' => env('ATTRIBUTES_HISTORY', false),
        'table' => 'attribute_revisions',
    ],
    'definitions' => [
        // 'rating'  => ['type' => 'integer', 'rules' => ['min:1', 'max:5'], 'required' => true],
        // 'sku'     => ['type' => 'string', 'unique' => 'global'],
        // 'token'   => ['type' => 'string', 'encrypted' => true],
        // 'retries' => ['type' => 'integer', 'default' => 3],
    ],
];

Every key

KeyDefaultEnvPurpose
modelAttribute::class—Eloquent model that stores attributes. Must be the packaged Attribute model or a subclass of it; anything else throws.
tableattributes—Table used by the migration and the model. A blank value is not set and uses the default; a non-string value throws.
key_typebigintATTRIBUTES_KEY_TYPEOwner key type for the morph columns: bigint, uuid or ulid (case-insensitive; anything else throws InvalidConfigurationException when the migrations run). Read when the migrations run.
strictfalseATTRIBUTES_STRICTReject writes — a value or its meta — to names with neither a global nor a model-schema definition (UnknownAttributeException).
prune_after_days30ATTRIBUTES_PRUNE_AFTER_DAYSDefault age in days for attributes:prune. A whole number, 0 or more (0 purges every trashed attribute); blank (ATTRIBUTES_PRUNE_AFTER_DAYS=) is not set and gives 30; anything else throws.
history.enabledfalseATTRIBUTES_HISTORYRecord an old→new revision on every attach, update, meta change and detach.
history.tableattribute_revisions—Table for the audit trail. A blank value is not set and uses the default; a non-string value throws.
definitions[]—Registry seed, keyed by attribute name; each entry is an array. Loaded once at boot.

Definition keys

Each entry under definitions is keyed by attribute name and accepts these keys:

Definition keyTypePurpose
typestringstring, integer, float, boolean, array or datetime (or the AttributeType case) — values are validated against it and stored in it ('5' becomes 5 for integer). Unset or blank means string; anything else throws.
rulesarrayExtra Laravel validation rules, applied after the type’s own rule. Must be an array (['min:1', 'max:5']); a pipe string throws.
requiredboolEnforced by $model->validateAttributes(). Read like the boolean env values; anything else throws.
defaultmixedReturned by reads when the attribute is not attached. Never persisted.
uniquestring / boolowner or true (per owner type), global (across every owner), none or false (unset or blank also means none); anything else throws instead of switching uniqueness off. Backed by a database unique index — encrypted values included.
encryptedboolStores the value as Crypt ciphertext at rest. Read like the boolean env values; anything else throws.
// config/attributes.php
'definitions' => [
    'rating'  => ['type' => 'integer', 'rules' => ['min:1', 'max:5'], 'required' => true],
    'sku'     => ['type' => 'string', 'unique' => 'global'],
    'token'   => ['type' => 'string', 'encrypted' => true],
    'retries' => ['type' => 'integer', 'default' => 3],
],

Config definitions are loaded into the registry once, when the app boots; an invalid entry throws InvalidConfigurationException at boot, naming attributes.definitions.<name>.<key>. You can also register definitions in code or declare them per model — see Definitions & validation and Per-model schemas.

Environment

The deployment-sensitive keys are env-backed:

# bigint | uuid | ulid — set before you run the migrations
ATTRIBUTES_KEY_TYPE=bigint

# reject attribute names that are not registered
ATTRIBUTES_STRICT=false

# default age (days) for attributes:prune
ATTRIBUTES_PRUNE_AFTER_DAYS=30

# record an old -> new revision on every change
ATTRIBUTES_HISTORY=false

The boolean env values accept true/false, 1/0, on/off and yes/no. Every setting is read strictly: a key that is not set — absent, null or blank (a host’s KEY=) — takes its default, and any other invalid value throws InvalidConfigurationException naming the key — it never falls back silently.

Check the resolved values at any time with Laravel’s about command. Definitions are reported by count only, never by name — an attribute name often names the very secret the encrypted flag protects:

php artisan about --only=attributes

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 crypto

By 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.