Overview
Attributes allow custom data to be stored against Eloquent models. They are most commonly used with products, where different information needs to be stored and presented to visitors. For example, a television might have the following attributes assigned:- Screen Size
- Screen Technology
- Tuner
- Resolution
product and brand), and ProductType records separately declare which of those attributes each product type actually presents to its products and variants.
Attribute Groups
Fields
Relationships
Attributes
Fields
Relationships
Scopes
Methods
Which model types an attribute applies to
Lunar\Core\Models\Attribute does not carry a morph column for the model type it belongs to. Instead, each attribute has a models relationship to Lunar\Core\Models\AttributeModel, a simple table pairing an attribute_id with a model_type string (the morph alias, e.g. product, brand, collection). An attribute can apply to more than one model type.
CreatesAttribute / UpdatesAttribute action contracts, which accept a model_types key and manage the AttributeModel rows for you.
Attributes on a Product Type
Lunar\Core\Models\ProductType declares which of the available attributes it exposes to its products and variants, through the product_type_attribute pivot table (the attributeMapping relationship). This is a separate concern from AttributeModel: AttributeModel says which model type an attribute is valid for; ProductType says which of those attributes a specific product type actually presents.
Field Types
Field types determine how an attribute’s value is stored and retrieved. Each type implementsLunar\Core\Contracts\FieldType and extends Lunar\Core\FieldTypes\AbstractFieldType.
These type keys are backed by
Lunar\Core\Enums\FieldTypeEnum, which is the source of the default entries in the FieldTypeManifest.
Each field type can describe its own configuration through two methods on the FieldType contract:
getConfig()returns the validation rules for the attribute’sconfigurationarray.getConfigurationFields()returns a renderer-agnostic description of the configuration inputs (akey, an inputtypesuch astext,number,toggle,select,tags, orlookups, and alabel), which an admin UI can use to build the attribute’s configuration form.
Custom Field Types
Custom field types can be created by extendingLunar\Core\FieldTypes\AbstractFieldType (or implementing Lunar\Core\Contracts\FieldType directly) and registering the type with the FieldTypeManifest in a service provider:
attributes.type; the second is the field type class. To make a custom field type editable in the admin panel, a corresponding admin component is also needed.
Models That Use Attributes
The following models support attributes out of the box, via theLunar\Core\Models\Concerns\HasAttributeData trait:
Lunar\Core\Models\ProductLunar\Core\Models\ProductVariantLunar\Core\Models\ProductTypeLunar\Core\Models\CollectionLunar\Core\Models\CustomerLunar\Core\Models\BrandLunar\Core\Models\CustomerGroup
Saving Attribute Data
Attribute values are stored in anattribute_data JSON column on the model. On disk, values are stored keyed by the attribute’s numeric id, so renaming an attribute’s handle never disconnects stored data. When assigning or reading the column, use the attribute’s handle as the key: the Lunar\Core\Casts\AsAttributeData cast resolves handles to ids (and back) via an internal AttributeCache.
Accessing Attribute Data
When theattribute_data property is accessed, it is hydrated into a collection of field type instances keyed by handle.
Retrieving a Single Attribute Value
ThetranslateAttribute method, from the HasAttributeData trait, returns the resolved value for a single attribute. For TranslatedText fields, it resolves the correct locale automatically, falling back to the first available value.
attr method does the same thing:
translateAttribute returns the raw value directly:
All attributes mapped to a model
ThemappedAttributes() method (also exposed as the mappedAttributes accessor) returns every Attribute whose models relationship includes the calling model’s morph type, ordered by position.
Validation Rules
An attribute can carry its own Laravel validation rules invalidation_rules, stored as a list of rule strings (for example ['min:1', 'max:10']). Core stores and exposes these rules; it does not enforce them automatically when attribute_data is written outside of an admin panel — enforcement is the responsibility of the editing surface (the Filament and Inertia admin panels apply them to their attribute forms).
Lunar\Core\Rules\ValidRuleString is a Laravel validation rule that checks a rule string is well-formed (a recognized rule name with valid parameters), useful when building a form that lets staff author validation_rules entries.
Adding Attributes to a Custom Model
To make a custom model support attributes:- Add the
HasAttributeDatatrait. - Add an
attribute_dataJSON column to the model’s database table. - Register the model as an attributable type so that attributes can target it.
HasAttributeData trait merges the attribute_data cast automatically, so no $casts entry is needed.
Attribute Manifest
Lunar\Core\Manifests\AttributeManifest, accessed through the Lunar\Core\Facades\AttributeManifest facade, manages which model types support attributes and caches searchable attribute lookups per type.
Product, ProductVariant, ProductType, Collection, Customer, Brand, and CustomerGroup are registered as attributable types out of the box.