> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laravelshopper.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Attributes

> Complete reference for the Attribute model, field types, values, and usage in Shopper.

Attributes define product characteristics like Color, Size, or Material. They enable variable products, enhance filtering, and provide detailed product specifications.

## Models

Shopper uses three models to manage attributes:

| Model                                  | Purpose                                                    |
| -------------------------------------- | ---------------------------------------------------------- |
| `Shopper\Core\Models\Attribute`        | The attribute definition (Color, Size, Material)           |
| `Shopper\Core\Models\AttributeValue`   | Possible values for an attribute (Red, Blue, Large)        |
| `Shopper\Core\Models\AttributeProduct` | Pivot linking attributes to products with a selected value |

The Attribute model implements `Shopper\Core\Models\Contracts\Attribute` and uses the `HasSlug` trait for automatic slug generation. Unlike products or brands, the Attribute model is not configurable via `config/shopper/models.php` and has no admin model wrapper.

## Database Schema

### Attribute Table

| Column          | Type      | Nullable | Default | Description                      |
| --------------- | --------- | -------- | ------- | -------------------------------- |
| `id`            | bigint    | no       | auto    | Primary key                      |
| `name`          | string    | no       | -       | Attribute name                   |
| `slug`          | string    | yes      | auto    | URL-friendly identifier (unique) |
| `description`   | string    | yes      | null    | Attribute description            |
| `type`          | string    | no       | -       | Field type enum value            |
| `icon`          | string    | yes      | null    | Icon identifier                  |
| `is_enabled`    | boolean   | no       | false   | Attribute visibility             |
| `is_searchable` | boolean   | no       | false   | Include in search                |
| `is_filterable` | boolean   | no       | false   | Show in filters                  |
| `created_at`    | timestamp | yes      | null    | Creation timestamp               |
| `updated_at`    | timestamp | yes      | null    | Last update timestamp            |

### AttributeValue Table

| Column         | Type       | Nullable | Default | Description              |
| -------------- | ---------- | -------- | ------- | ------------------------ |
| `id`           | bigint     | no       | auto    | Primary key              |
| `value`        | string(50) | no       | -       | Display value            |
| `key`          | string     | no       | -       | Unique identifier key    |
| `position`     | smallint   | yes      | 1       | Display order            |
| `attribute_id` | bigint     | no       | -       | Foreign key to attribute |

### AttributeProduct Table (Pivot)

| Column                   | Type     | Nullable | Description                            |
| ------------------------ | -------- | -------- | -------------------------------------- |
| `id`                     | bigint   | no       | Primary key                            |
| `attribute_id`           | bigint   | no       | Foreign key to attribute               |
| `product_id`             | bigint   | no       | Foreign key to product                 |
| `attribute_value_id`     | bigint   | yes      | Foreign key to attribute value         |
| `attribute_custom_value` | longtext | yes      | Custom value for text-based attributes |

## Field Types

Attributes use the `FieldType` enum to determine input behavior:

```php theme={null}
use Shopper\Core\Enum\FieldType;

FieldType::Checkbox     // Multiple selectable values
FieldType::ColorPicker  // Color selection
FieldType::DatePicker   // Date input
FieldType::RichText     // Rich text editor
FieldType::Select       // Single selection dropdown
FieldType::Text         // Single-line text input
FieldType::Number       // Numeric input
```

| Type        | Database Value | Has Predefined Values | Description                     |
| ----------- | -------------- | --------------------- | ------------------------------- |
| Checkbox    | `checkbox`     | Yes                   | Multiple values can be selected |
| ColorPicker | `colorpicker`  | Yes                   | Color values with picker        |
| DatePicker  | `datepicker`   | No                    | Date input field                |
| RichText    | `richtext`     | No                    | HTML content editor             |
| Select      | `select`       | Yes                   | Single value selection          |
| Text        | `text`         | No                    | Free text input                 |
| Number      | `number`       | No                    | Integer or decimal input        |

### Type Checking Methods

Each attribute type has helper methods to determine its behavior:

```php theme={null}
$attribute->hasMultipleValues();
$attribute->hasSingleValue();
$attribute->hasTextValue();
Attribute::fieldsWithValues();
```

`hasMultipleValues()` returns `true` for Checkbox and ColorPicker. `hasSingleValue()` returns `true` for Select. `hasTextValue()` returns `true` for Text, Number, RichText, and DatePicker. `fieldsWithValues()` returns the types that require predefined values.

## Relationships

### Values

```php theme={null}
$attribute->values;
```

To add values to an attribute:

```php theme={null}
$attribute->values()->create([
    'value' => 'Red',
    'key' => 'color-red',
    'position' => 1,
]);
```

```php theme={null}
$attribute->values()->createMany([
    ['value' => 'Small', 'key' => 'size-s', 'position' => 1],
    ['value' => 'Medium', 'key' => 'size-m', 'position' => 2],
    ['value' => 'Large', 'key' => 'size-l', 'position' => 3],
]);
```

### Products

```php theme={null}
$attribute->products;
```

Attach an attribute to a product with a predefined value:

```php theme={null}
$attribute->products()->attach($productId, [
    'attribute_value_id' => $valueId,
]);
```

Or with a custom value:

```php theme={null}
$attribute->products()->attach($productId, [
    'attribute_custom_value' => 'Custom specification',
]);
```

### Variants (AttributeValue)

AttributeValue can be linked to product variants:

```php theme={null}
$attributeValue->variants;
$attributeValue->variants()->attach($variantId);
```

## Slug & Lookup

The `HasSlug` trait generates unique slugs automatically and provides a `findBySlug()` static method:

```php theme={null}
use Shopper\Core\Models\Attribute;

$attribute = Attribute::findBySlug('color');
```

## Query Scopes

Filter attributes by their visibility and behavior flags:

```php theme={null}
use Shopper\Core\Models\Attribute;

Attribute::query()->enabled()->get();
Attribute::query()->isFilterable()->get();
Attribute::query()->isSearchable()->get();
```

Scopes can be combined:

```php theme={null}
Attribute::query()
    ->enabled()
    ->isFilterable()
    ->with('values')
    ->get();
```

## Status Management

```php theme={null}
$attribute->updateStatus(true);
$attribute->updateStatus(false);
```

## Display Helpers

```php theme={null}
$attribute->type_formatted;
Attribute::typesFields();
```

`type_formatted` returns a translated label like "Checkbox". `typesFields()` returns all available types with their labels.

## Working with AttributeProduct

The `AttributeProduct` model provides a computed `real_value` accessor:

```php theme={null}
use Shopper\Core\Models\AttributeProduct;

$attributeProduct = AttributeProduct::query()->find($id);

// Get the actual value (custom or from value relationship)
$attributeProduct->real_value;
// Returns attribute_custom_value if set, otherwise value->value
```

## Creating Attributes

### Attribute with Predefined Values

```php theme={null}
use Shopper\Core\Models\Attribute;
use Shopper\Core\Enum\FieldType;

// Create a color attribute
$color = Attribute::query()->create([
    'name' => 'Color',
    'slug' => 'color',
    'type' => FieldType::ColorPicker,
    'is_enabled' => true,
    'is_filterable' => true,
]);

// Add color values
$color->values()->createMany([
    ['value' => 'Red', 'key' => 'red', 'position' => 1],
    ['value' => 'Blue', 'key' => 'blue', 'position' => 2],
    ['value' => 'Green', 'key' => 'green', 'position' => 3],
]);
```

### Attribute with Free Text

```php theme={null}
// Create a text attribute (no predefined values needed)
$material = Attribute::query()->create([
    'name' => 'Material',
    'slug' => 'material',
    'type' => FieldType::Text,
    'is_enabled' => true,
    'is_searchable' => true,
]);
```

## Assigning Attributes to Products

```php theme={null}
use Shopper\Models\Product;

$product = Product::query()->find($id);

// Assign attribute with predefined value (via options relationship)
$product->options()->attach($attributeId, [
    'attribute_value_id' => $valueId,
]);

// Assign attribute with custom value
$product->options()->attach($attributeId, [
    'attribute_custom_value' => '100% Cotton',
]);

// Get product attributes with values
foreach ($product->options as $attribute) {
    $valueId = $attribute->pivot->attribute_value_id;
    $customValue = $attribute->pivot->attribute_custom_value;
}
```

## Retrieving Attributes

```php theme={null}
use Shopper\Core\Models\Attribute;

// Get all enabled attributes with values
$attributes = Attribute::query()
    ->enabled()
    ->with('values')
    ->get();

// Get filterable attributes for storefront
$filters = Attribute::query()
    ->enabled()
    ->isFilterable()
    ->with(['values' => fn ($q) => $q->orderBy('position')])
    ->get();

// Get attribute by slug
$size = Attribute::findBySlug('size');
$size->load('values');
```

## Observer Behavior

The `AttributeObserver` handles cleanup when deleting:

```php theme={null}
// When an attribute is deleted:
// 1. All product associations are detached
// 2. All attribute values are deleted

$attribute->delete(); // Triggers observer cleanup
```

## Disabling Attribute Feature

```php theme={null}
// config/shopper/features.php
use Shopper\Enum\FeatureState;

return [
    'attribute' => FeatureState::Disabled,
];
```

## Permissions

The admin panel generates five permissions for attribute management:

| Permission          | Description              |
| ------------------- | ------------------------ |
| `browse_attributes` | View the attributes list |
| `read_attributes`   | View a single attribute  |
| `add_attributes`    | Create new attributes    |
| `edit_attributes`   | Edit existing attributes |
| `delete_attributes` | Delete attributes        |

## Components

Attribute components are part of the product configuration. To customize them:

```bash theme={null}
php artisan shopper:component:publish product
```

Attribute-related components in `config/shopper/components/product.php`:

```php theme={null}
use Shopper\Livewire;

return [
    'pages' => [
        // ...
        'attribute-index' => Livewire\Pages\Attribute\Browse::class,
    ],
    'components' => [
        // ...
        'slide-overs.attribute-form' => Livewire\SlideOvers\AttributeForm::class,
        'slide-overs.choose-product-attributes' => Livewire\SlideOvers\ChooseProductAttributes::class,
        'slide-overs.attribute-values' => Livewire\SlideOvers\AttributeValues::class,
    ],
];
```

## Storefront Example

```php theme={null}
namespace App\Http\Controllers;

use Shopper\Core\Models\Attribute;
use Shopper\Models\Product;

class ProductFilterController extends Controller
{
    public function index()
    {
        // Get filterable attributes for sidebar
        $filters = Attribute::query()
            ->enabled()
            ->isFilterable()
            ->with(['values' => fn ($q) => $q->orderBy('position')])
            ->get();

        return view('products.index', compact('filters'));
    }

    public function filter(Request $request)
    {
        $query = Product::query()->publish();

        foreach ($request->input('attributes', []) as $slug => $values) {
            $query->whereHas('options', function ($q) use ($slug, $values) {
                $q->where('slug', $slug)
                    ->wherePivotIn('attribute_value_id', $values);
            });
        }

        return $query->paginate(12);
    }
}
```

## Use Cases

| Attribute Type | Example           | Use Case                              |
| -------------- | ----------------- | ------------------------------------- |
| Checkbox       | Size              | Multiple sizes available for clothing |
| ColorPicker    | Color             | Product color options                 |
| Select         | Material          | Single material selection             |
| Text           | SKU Suffix        | Custom text per product               |
| Number         | Weight            | Numeric specifications                |
| DatePicker     | Release Date      | Product launch date                   |
| RichText       | Care Instructions | Detailed HTML content                 |
