PHPackages                             fiachehr/laravel-eav - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. fiachehr/laravel-eav

ActiveLibrary[Database &amp; ORM](/categories/database)

fiachehr/laravel-eav
====================

A complete Entity-Attribute-Value (EAV) package for Laravel

1.0.5(3mo ago)62512[2 issues](https://github.com/fiachehr/laravel-eav/issues)MITPHPPHP ^8.3

Since Dec 29Pushed 3mo agoCompare

[ Source](https://github.com/fiachehr/laravel-eav)[ Packagist](https://packagist.org/packages/fiachehr/laravel-eav)[ RSS](/packages/fiachehr-laravel-eav/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (12)Versions (7)Used By (0)

Laravel EAV Package
===================

[](#laravel-eav-package)

A complete and powerful Entity-Attribute-Value (EAV) package for Laravel.

Documentation
-------------

[](#documentation)

**[Laravel EAV — Documentation](https://fiachehr.ir/docs/laravel-eav.html)** (hosted on [fiachehr.ir](https://fiachehr.ir))

Features
--------

[](#features)

- ✅ Clean architecture (Domain, Application, Infrastructure, Presentation)
- ✅ MorphTo relationships support for any model
- ✅ Attribute groups management
- ✅ **20+ attribute types** (Text, Textarea, Number, Decimal, Date, DateTime, Boolean, File, and more)
- ✅ **Flexible validation system** with validation rules (Email, URL, Image, Video, etc. can be applied via validations)
- ✅ **Optimized database structure** with separate columns for different data types
- ✅ **Advanced search and filtering** capabilities
- ✅ **Query Builder** for complex EAV queries
- ✅ **Indexed columns** for fast searches
- ✅ **Multilingual support** with language-based filtering and optional translation system integration
- ✅ Validation support
- ✅ Easy to use trait for models
- ✅ Backward compatible with existing data

Requirements
------------

[](#requirements)

- PHP &gt;= 8.3
- Laravel **10.x**, **11.x**, or **12.x** (see `composer.json` `illuminate/*` constraints)

Installation
------------

[](#installation)

```
composer require fiachehr/laravel-eav
```

After installation, publish and run the migrations:

```
php artisan migrate
```

Usage
-----

[](#usage)

### 1. Use the Trait in Your Models

[](#1-use-the-trait-in-your-models)

```
use Fiachehr\LaravelEav\Domain\Shared\Traits\HasAttributes;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasAttributes;

    // Your model code...
}
```

### 2. Working with Attributes

[](#2-working-with-attributes)

#### 2.1. Getting Attribute Values

[](#21-getting-attribute-values)

```
// Get all attributes with their values
$product->eavAttributes; // Returns collection with pivot values

// Get attribute value by ID or slug
$value = $product->getEavAttributeValue(1); // by ID
$value = $product->getEavAttributeValue('color'); // by slug
$value = $product->getEavAttributeValueBySlug('color');

// Get all attribute values as key-value pairs
// Keys can be 'id', 'slug', or 'logical_id'
$values = $product->getEavAttributeValues('slug');
// Returns: ['color' => 'red', 'size' => 'large', 'price' => 100]

$values = $product->getEavAttributeValues('id');
// Returns: [1 => 'red', 2 => 'large', 3 => 100]

// Get all attribute values as Eloquent models
$attributeValues = $product->eavAttributeValues;
// Returns collection of EloquentAttributeValue models
```

#### 2.2. Setting Attribute Values

[](#22-setting-attribute-values)

```
// Set attribute values (by ID or slug)
$product->setEavAttributeValues([
    1 => 'Value 1',           // by ID
    'color' => 'red',         // by slug
    'size' => 'large',        // by slug
    'price' => 100.50,        // number
    'is_active' => true,      // boolean
    'created_at' => '2024-01-01', // date
]);

// Set a single attribute value
$product->setEavAttributeValue('color', 'blue');
$product->setEavAttributeValue(1, 'new value');

// Sync attribute values (removes old ones not in the array)
$product->syncEavAttributeValues([
    'color' => 'red',
    'size' => 'medium',
]);

// Remove a specific attribute
$product->removeEavAttributeValue('color');
$product->removeEavAttributeValue(1);

// Clear all attribute values
$product->clearEavAttributeValues();
```

### 3. Validation System

[](#3-validation-system)

You can apply validations to attributes to ensure data integrity. Validations are applied based on the attribute type.

#### 3.1. Setting Validations

[](#31-setting-validations)

```
use Fiachehr\LaravelEav\Domain\Enums\AttributeType;
use Fiachehr\LaravelEav\Domain\Enums\ValidationType;

// Create an attribute with email validation
$attribute = Attribute::create([
    'title' => 'Email Address',
    'type' => AttributeType::TEXT,
    'validations' => [
        ValidationType::REQUIRED->value,
        ValidationType::EMAIL->value,
    ],
]);

// Create an attribute with image file validation
$attribute = Attribute::create([
    'title' => 'Profile Image',
    'type' => AttributeType::FILE,
    'validations' => [
        ValidationType::REQUIRED->value,
        ValidationType::IMAGE->value,
        ['type' => ValidationType::MAX_FILE_SIZE->value, 'parameter' => 2048], // 2MB
    ],
]);

// Create an attribute with min/max length validation
$attribute = Attribute::create([
    'title' => 'Description',
    'type' => AttributeType::TEXTAREA,
    'validations' => [
        ValidationType::REQUIRED->value,
        ['type' => ValidationType::MIN_LENGTH->value, 'parameter' => 10],
        ['type' => ValidationType::MAX_LENGTH->value, 'parameter' => 500],
    ],
]);
```

#### 3.2. Validating Attribute Values

[](#32-validating-attribute-values)

```
use Fiachehr\LaravelEav\Domain\Services\AttributeValidator;

$validator = new AttributeValidator();

try {
    // Validate a value against attribute validations
    $validator->validate(
        AttributeType::TEXT,
        'user@example.com',
        [ValidationType::EMAIL->value]
    );

    // Value is valid
} catch (\Illuminate\Validation\ValidationException $e) {
    // Handle validation errors
    $errors = $e->validator->errors();
}
```

#### 3.3. Getting Laravel Validation Rules

[](#33-getting-laravel-validation-rules)

```
use Fiachehr\LaravelEav\Domain\Services\AttributeValidator;

$validator = new AttributeValidator();

// Get Laravel validation rules for an attribute
$rules = $validator->getValidationRules(
    AttributeType::TEXT,
    [
        ValidationType::REQUIRED->value,
        ValidationType::EMAIL->value,
        ['type' => ValidationType::MAX_LENGTH->value, 'parameter' => 255],
    ]
);

// Use in Laravel Form Request
$request->validate([
    'email' => $rules,
]);
```

### 4. Multilingual Support

[](#4-multilingual-support)

The package provides built-in multilingual support for attributes and attribute groups. Each attribute and attribute group has a `language` field that stores the language code (e.g., 'en', 'fa', 'de').

#### 4.1. Creating Attributes with Language

[](#41-creating-attributes-with-language)

```
use Fiachehr\LaravelEav\Domain\Entities\Attribute;
use Fiachehr\LaravelEav\Domain\Enums\AttributeType;
use Fiachehr\LaravelEav\Domain\Repositories\AttributeRepositoryInterface;

// Create attribute in English
$attributeEn = new Attribute(
    id: null,
    logicalId: 'color-en',
    title: 'Color',
    slug: 'color',
    type: AttributeType::TEXT,
    description: 'Product color',
    values: [],
    validations: [],
    isActive: true,
    language: 'en'
);

// Create attribute in Persian
$attributeFa = new Attribute(
    id: null,
    logicalId: 'color-fa',
    title: 'رنگ',
    slug: 'color-fa',
    type: AttributeType::TEXT,
    description: 'رنگ محصول',
    values: [],
    validations: [],
    isActive: true,
    language: 'fa'
);

$repository = app(AttributeRepositoryInterface::class);
$repository->create($attributeEn);
$repository->create($attributeFa);
```

#### 4.2. Filtering by Language

[](#42-filtering-by-language)

##### Using Model Scopes

[](#using-model-scopes)

```
use Fiachehr\LaravelEav\Infrastructure\Persistence\Eloquent\EloquentAttribute;

// Get attributes for a specific language
$englishAttributes = EloquentAttribute::forLanguage('en')->get();
$persianAttributes = EloquentAttribute::forLanguage('fa')->get();

// Get attributes for current locale
$currentLanguageAttributes = EloquentAttribute::forCurrentLanguage()->get();

// Get attributes for multiple languages
$multiLanguageAttributes = EloquentAttribute::forLanguages(['en', 'fa', 'de'])->get();

// Exclude a specific language
$nonEnglishAttributes = EloquentAttribute::excludeLanguage('en')->get();

// Combine with other scopes
$activeEnglishAttributes = EloquentAttribute::forLanguage('en')
    ->where('is_active', true)
    ->get();
```

##### Using Repository Methods

[](#using-repository-methods)

```
use Fiachehr\LaravelEav\Domain\Repositories\AttributeRepositoryInterface;
use Fiachehr\LaravelEav\Domain\Repositories\AttributeGroupRepositoryInterface;

$attributeRepository = app(AttributeRepositoryInterface::class);
$groupRepository = app(AttributeGroupRepositoryInterface::class);

// Get attributes by language
$englishAttributes = $attributeRepository->findByLanguage('en');
$currentLanguageAttributes = $attributeRepository->findByCurrentLanguage();
$multiLanguageAttributes = $attributeRepository->findByLanguages(['en', 'fa']);

// Same for attribute groups
$englishGroups = $groupRepository->findByLanguage('en');
$currentLanguageGroups = $groupRepository->findByCurrentLanguage();
```

#### 4.3. Translation System

[](#43-translation-system)

The package includes a built-in translation system using the `eav_translations` table. This allows you to store translations for attribute fields (like `title` and `description`) in multiple languages.

##### Using the HasTranslations Trait

[](#using-the-hastranslations-trait)

To enable translations for your Attribute or AttributeGroup models, use the `HasTranslations` trait:

```
use Fiachehr\LaravelEav\Domain\Shared\Traits\HasTranslations;
use Fiachehr\LaravelEav\Infrastructure\Persistence\Eloquent\EloquentAttribute;

class Attribute extends EloquentAttribute
{
    use HasTranslations;

    // Define which fields are translatable
    protected $translatable = [
        'title',
        'description',
    ];
}
```

##### Getting Translations

[](#getting-translations)

```
use Fiachehr\LaravelEav\Infrastructure\Persistence\Eloquent\EloquentAttribute;

$attribute = EloquentAttribute::with('translations')->find(1);

// Get translation for a specific field and locale
$translatedTitle = $attribute->getTranslation('title', 'fa');
// Returns: 'رنگ' or null if not found

// Get all translations grouped by locale
$allTranslations = $attribute->getAllTranslations();
// Returns: ['en' => ['title' => 'Color', 'description' => '...'], 'fa' => ['title' => 'رنگ', ...]]

// Get translations for a specific locale
$persianTranslations = $attribute->getTranslationsForLocale('fa');
// Returns: ['title' => 'رنگ', 'description' => '...']

// Get translations for a specific key across all locales
$titleTranslations = $attribute->getTranslationsForKey('title');
// Returns: ['en' => 'Color', 'fa' => 'رنگ', 'de' => 'Farbe']

// Check if translation exists for a locale
if ($attribute->hasTranslation('fa')) {
    // Translation exists for Persian
}

// Check if translation exists for a specific key and locale
if ($attribute->hasTranslationForKey('title', 'fa')) {
    // Title translation exists for Persian
}

// Access translations relationship directly
$translations = $attribute->translations;
// Returns: Collection of EloquentTranslation models
```

##### Setting Translations

[](#setting-translations)

```
// Set a single translation
$attribute->setTranslation('title', 'fa', 'رنگ');
$attribute->setTranslation('description', 'fa', 'رنگ محصول');

// Set multiple translations at once
$attribute->setTranslations([
    'title' => [
        'en' => 'Color',
        'fa' => 'رنگ',
        'de' => 'Farbe',
    ],
    'description' => [
        'en' => 'Product color',
        'fa' => 'رنگ محصول',
        'de' => 'Produktfarbe',
    ],
]);

// Or using locale-first format
$attribute->setTranslations([
    'en' => [
        'title' => 'Color',
        'description' => 'Product color',
    ],
    'fa' => [
        'title' => 'رنگ',
        'description' => 'رنگ محصول',
    ],
]);
```

##### Deleting Translations

[](#deleting-translations)

```
// Delete a specific translation
$attribute->deleteTranslation('title', 'fa');

// Delete all translations for a specific locale
$attribute->deleteTranslationsForLocale('fa');

// Delete all translations for a specific key across all locales
$attribute->deleteTranslationsForKey('title');

// Delete all translations for this model
$attribute->deleteAllTranslations();
```

##### Using with Custom Models

[](#using-with-custom-models)

If you extend `EloquentAttribute` in your project, the translation system automatically uses the base class name for compatibility:

```
use Fiachehr\LaravelEav\Infrastructure\Persistence\Eloquent\EloquentAttribute as BaseEloquentAttribute;
use Fiachehr\LaravelEav\Domain\Shared\Traits\HasTranslations;

class Attribute extends BaseEloquentAttribute
{
    use HasTranslations;

    protected $translatable = ['title', 'description'];
}

// The translations relation will automatically work with existing data
// that uses the base class name (EloquentAttribute)
$attribute = Attribute::with('translations')->find(1);
$translations = $attribute->translations; // Works correctly!
```

##### Database Structure

[](#database-structure)

Translations are stored in the `eav_translations` table:

```
- id
- translatable_id (ID of the attribute/group)
- translatable_type (Model class name)
- locale (Language code: 'en', 'fa', 'de', etc.)
- key (Field name: 'title', 'description', etc.)
- value (Translation text)
```

**Note:** The translation system uses polymorphic relations, so it works seamlessly with models that extend `EloquentAttribute` or use the trait directly.

#### 4.4. Working with Multilingual Attributes in Models

[](#44-working-with-multilingual-attributes-in-models)

```
use Fiachehr\LaravelEav\Domain\Shared\Traits\HasAttributes;

class Product extends Model
{
    use HasAttributes;
}

// Get attributes for current language
$product = Product::find(1);
$currentLanguageAttributes = $product->eavAttributes()
    ->where('language', app()->getLocale())
    ->get();

// Or filter by specific language
$englishAttributes = $product->eavAttributes()
    ->where('language', 'en')
    ->get();
```

#### 4.5. Language Configuration

[](#45-language-configuration)

Make sure your Laravel application has the locale configured:

```
// config/app.php
'locale' => 'en',
'supported_locales' => ['en', 'fa', 'de', 'es'],
```

The package will automatically use `app()->getLocale()` for the `forCurrentLanguage()` scope.

### 5. Advanced Search and Filtering

[](#5-advanced-search-and-filtering)

#### 5.1. Using Model Scopes

[](#51-using-model-scopes)

```
// Search products by attribute value (exact match)
$products = Product::whereEavAttribute('color', 'red')->get();

// Search with LIKE (partial match)
$products = Product::whereEavAttributeLike('title', 'laptop')->get();

// Search by number range
$products = Product::whereEavAttributeBetween('price', 100, 500)->get();

// Search by date range
$products = Product::whereEavAttributeDateBetween('created_at', '2024-01-01', '2024-12-31')->get();

// Search where value is IN array
$products = Product::whereEavAttributeIn('color', ['red', 'blue', 'green'])->get();

// Search where value is NOT IN array
$products = Product::whereEavAttributeNotIn('status', ['deleted', 'archived'])->get();

// Search where value is NULL
$products = Product::whereEavAttributeNull('notes')->get();

// Search where value is NOT NULL
$products = Product::whereEavAttributeNotNull('description')->get();

// Multiple conditions (AND - all must match)
$products = Product::whereEavAttributes([
    ['attribute' => 'color', 'value' => 'red'],
    ['attribute' => 'size', 'value' => 'large', 'operator' => '='],
    ['attribute' => 'price', 'value' => 100, 'operator' => '>='],
])->get();

// Combine with other Laravel query methods
$products = Product::whereEavAttribute('color', 'red')
    ->where('status', 'active')
    ->orderBy('created_at', 'desc')
    ->paginate(20);
```

#### 5.2. Using Query Builder (Recommended for Complex Queries)

[](#52-using-query-builder-recommended-for-complex-queries)

```
use Fiachehr\LaravelEav\Infrastructure\Query\EavQueryBuilder;

// Basic usage - get product IDs matching criteria
$query = Product::eavQuery();
$query->whereText('color', 'red')
      ->whereNumber('price', '>', 100)
      ->whereBoolean('in_stock', true);

$productIds = $query->getAttributableIds();
$products = Product::whereIn('id', $productIds)->get();

// Or use the helper method
$products = Product::findByEav(function ($query) {
    $query->whereText('color', 'red')
          ->whereNumberBetween('price', 100, 500)
          ->whereDateBetween('created_at', '2024-01-01', '2024-12-31');
});
```

#### 5.3. Text Search Methods

[](#53-text-search-methods)

```
$query = Product::eavQuery();

// Exact match
$query->whereText('title', 'Laptop');

// LIKE search (contains)
$query->whereTextLike('description', 'gaming');

// IN array
$query->whereTextIn('color', ['red', 'blue', 'green']);

// NOT IN array
$query->whereTextNotIn('status', ['deleted', 'archived']);

// IS NULL
$query->whereTextNull('notes');

// IS NOT NULL
$query->whereTextNotNull('description');
```

#### 5.4. Number Search Methods

[](#54-number-search-methods)

```
$query = Product::eavQuery();

// Exact match
$query->whereNumber('price', 100);

// Comparison operators
$query->whereNumber('price', '>', 100);
$query->whereNumber('price', '>=', 100);
$query->whereNumber('price', '', 50.00);
$query->whereDecimal('price', '=', '2024-01-01');
$query->whereDate('created_at', '=', '2024-01-01 00:00:00');
```

#### 5.7. Boolean Search Methods

[](#57-boolean-search-methods)

```
$query = Product::eavQuery();

// Boolean value
$query->whereBoolean('is_active', true);
$query->whereBoolean('is_featured', false);

// Shortcuts
$query->whereTrue('is_active');
$query->whereFalse('is_deleted');
```

#### 5.8. JSON Search Methods

[](#58-json-search-methods)

```
$query = Product::eavQuery();

// JSON contains key-value
$query->whereJsonContains('metadata', 'tags', 'electronics');
$query->whereJsonContains('specifications', 'ram', '8GB');
```

#### 5.9. Multiple Conditions

[](#59-multiple-conditions)

```
$query = Product::eavQuery();

// AND conditions (all must match)
$query->whereText('color', 'red')
      ->whereNumber('price', '>', 100)
      ->whereBoolean('in_stock', true);

// OR conditions (any can match)
$query->whereAny([
    ['attribute' => 'color', 'value' => 'red'],
    ['attribute' => 'color', 'value' => 'blue'],
    ['attribute' => 'color', 'value' => 'green'],
]);

// Complex: (color = red AND price > 100) OR (color = blue AND price < 50)
$query->where(function ($q) {
    $q->whereText('color', 'red')
      ->whereNumber('price', '>', 100);
})->orWhere(function ($q) {
    $q->whereText('color', 'blue')
      ->whereNumber('price', '', 100);
})->orWhere(function ($q) {
    $q->whereText('size', 'large')
      ->whereNumber('price', '', 100);

// Get matching entity IDs
$productIds = $query->getAttributableIds();
$products = Product::whereIn('id', $productIds)->get();

// Get count
$count = $query->count();

// Get all attribute values for matching entities
$colors = $query->getAttributeValues('color');

// Get distinct attribute values
$uniqueColors = $query->getDistinctAttributeValues('color');

// Get the underlying query builder for advanced operations
$dbQuery = $query->getQuery();
$results = $dbQuery->get();
```

#### 5.13. Selecting Specific Attributes

[](#513-selecting-specific-attributes)

```
// Get products with only specific attributes loaded
$products = Product::with(['eavAttributes' => function ($query) {
    $query->whereIn('slug', ['color', 'size', 'price']);
}])->get();

// Get attribute values for specific attributes only
$product = Product::find(1);
$specificValues = $product->eavAttributes()
    ->whereIn('slug', ['color', 'size'])
    ->get()
    ->mapWithKeys(function ($attr) {
        return [$attr->slug => $attr->pivot->value_text ?? $attr->pivot->value_number ?? $attr->pivot->value];
    });

// Get products with their attribute values as array
$products = Product::with('eavAttributes')->get()->map(function ($product) {
    return [
        'id' => $product->id,
        'name' => $product->name,
        'attributes' => $product->getEavAttributeValues('slug'),
    ];
});
```

#### 5.14. Aggregate Functions

[](#514-aggregate-functions)

```
$query = Product::eavQuery();
$query->whereText('category', 'electronics');

// Get sum of prices
$totalPrice = $query->sum('price');

// Get average price
$avgPrice = $query->avg('price');

// Get minimum price
$minPrice = $query->min('price');

// Get maximum price
$maxPrice = $query->max('price');

// Get count
$count = $query->count();
```

### 6. Working with Attribute Groups

[](#6-working-with-attribute-groups)

```
// Get all attribute groups
$product->eavAttributeGroups;

// Attach groups
$product->attachEavAttributeGroups([1, 2, 3]);

// Sync groups (replaces all existing)
$product->syncEavAttributeGroups([1, 2]);

// Detach groups
$product->detachEavAttributeGroups([1]);

// Get attributes through groups
$attributes = $product->getEavAttributesThroughGroups();
```

### 7. Available Attribute Types

[](#7-available-attribute-types)

The package supports **20+ attribute types** with a flexible validation system:

#### Text Types

[](#text-types)

- `TEXT` - Simple text input (can be validated as Email, URL, Slug, etc.)
- `TEXTAREA` - Multi-line text (can be validated as Rich Text, Markdown, JSON, etc.)
- `PASSWORD` - Password field (with built-in password validation)

#### Number Types

[](#number-types)

- `NUMBER` - Integer
- `DECIMAL` - Decimal/Float

#### Selection Types

[](#selection-types)

- `RADIO` - Radio buttons
- `SELECT` - Dropdown select
- `MULTIPLE` - Multiple select
- `CHECKBOX` - Checkbox
- `COLOR` - Color picker

#### Date/Time Types

[](#datetime-types)

- `DATE` - Date only
- `TIME` - Time only
- `DATETIME` - Date and time

#### Boolean Types

[](#boolean-types)

- `BOOLEAN` - True/False

#### File Types

[](#file-types)

- `FILE` - File upload (can be validated as Image, Video, Audio, Document, etc.)

#### Location Types

[](#location-types)

- `LOCATION` - Location name
- `COORDINATES` - GPS coordinates

### 7.1. Validation System

[](#71-validation-system)

Instead of having separate types for Email, URL, Image, Video, etc., you can use the validation system to apply specific validations to base types:

**Example:**

- Use `TEXT` type with `email` validation for email fields
- Use `TEXT` type with `url` validation for URL fields
- Use `FILE` type with `image` validation for image uploads
- Use `FILE` type with `video` validation for video uploads
- Use `TEXTAREA` type with `json` validation for JSON data

**Available Validations:**

- Text: `required`, `min_length`, `max_length`, `email`, `url`, `slug`, `password`, `regex`
- Number: `required`, `min`, `max`, `integer`, `decimal`
- File: `required`, `image`, `video`, `audio`, `document`, `max_file_size`, `allowed_mime_types`
- Format: `json`, `array`, `rich_text`, `markdown`
- Date: `required`, `date_format`, `after`, `before`

### 8. Database Optimization

[](#8-database-optimization)

The package uses an optimized database structure with separate columns for different data types:

- `value_text` - For text-based attributes (indexed)
- `value_number` - For integer values (indexed)
- `value_decimal` - For decimal values (indexed)
- `value_date` - For date values (indexed)
- `value_datetime` - For datetime values (indexed)
- `value_time` - For time values
- `value_boolean` - For boolean values (indexed)
- `value_json` - For complex data (JSON)

This structure allows for:

- **Fast searches** on indexed columns
- **Type-specific queries** (number ranges, date ranges, etc.)
- **Better performance** compared to storing everything as text

### 9. Real-World Examples

[](#9-real-world-examples)

#### Example 1: E-commerce Product Search

[](#example-1-e-commerce-product-search)

```
// Find products with specific criteria
$products = Product::findByEav(function ($query) {
    $query->whereTextIn('color', ['red', 'blue', 'green'])
          ->whereNumberBetween('price', 50, 200)
          ->whereBoolean('in_stock', true)
          ->whereDateBetween('created_at', '2024-01-01', '2024-12-31')
          ->orderByNumber('price', 'asc')
          ->limit(20);
});
```

#### Example 2: User Profile Filtering

[](#example-2-user-profile-filtering)

```
// Find users with specific attributes
$users = User::findByEav(function ($query) {
    $query->whereText('city', 'Tehran')
          ->whereNumber('age', '>=', 18)
          ->whereNumber('age', '', 100);
    });

    // Less efficient - Multiple queries
    $products = Product::whereEavAttribute('color', 'red')
        ->whereEavAttribute('price', '>', 100)
        ->get();
    ```

Troubleshooting
---------------

[](#troubleshooting)

### Attribute values not saving correctly

[](#attribute-values-not-saving-correctly)

Make sure you're using the correct data type for the attribute. The package automatically stores values in the appropriate column based on the attribute type.

### Slow queries

[](#slow-queries)

- Check if indexes are created properly
- Use eager loading to avoid N+1 queries
- Consider caching frequently accessed attributes
- Use Query Builder for complex searches instead of multiple scopes

### Migration errors

[](#migration-errors)

If you're updating from an older version, make sure to run the update migration:

```
php artisan migrate
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

Changelog
---------

[](#changelog)

### Version 1.0.0

[](#version-100)

- Initial release
- 20+ attribute types support
- Optimized database structure with separate columns for different data types
- Advanced search and filtering capabilities
- Query Builder for complex EAV queries
- Multilingual support with translation system
- Comprehensive validation system
- Clean architecture
- Full test coverage (126 tests, 322 assertions)

Support
-------

[](#support)

For issues and questions, please open an issue on GitHub.

License
-------

[](#license)

MIT

---

**Made with ❤️ by Fiachehr Pourmojib**

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance76

Regular maintenance activity

Popularity21

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~18 days

Total

6

Last Release

94d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/535c8f29f90b6f75ba28d952c79d2861c115652851314b7f6330e204493f1c48?d=identicon)[fiachehr](/maintainers/fiachehr)

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fiachehr-laravel-eav/health.svg)

```
[![Health](https://phpackages.com/badges/fiachehr-laravel-eav/health.svg)](https://phpackages.com/packages/fiachehr-laravel-eav)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M96](/packages/mongodb-laravel-mongodb)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[yajra/laravel-oci8

Oracle DB driver for Laravel via OCI8

8793.2M25](/packages/yajra-laravel-oci8)[glushkovds/phpclickhouse-laravel

Adapter of the most popular library https://github.com/smi2/phpClickHouse to Laravel

2051.5M2](/packages/glushkovds-phpclickhouse-laravel)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)[laravel-liberu/laravel-gedcom

A package that converts gedcom files to Eloquent models

782.5k1](/packages/laravel-liberu-laravel-gedcom)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
