laravel-eav maintained by abdylreshit
Laravel EAV
A lightweight, powerful EAV (Entity-Attribute-Value) package for Laravel. Add dynamic, typed attributes to any Eloquent model without modifying your database schema. Perfect for e-commerce platforms, CMS systems, and applications requiring flexible data structures.
Features
✨ Dynamic Attributes - Add unlimited attributes to any model without schema changes
🎯 Type Support - String, text, integer, decimal, boolean, date, datetime, JSON, image, and file types
✅ Validation Ready - Built-in validation support for attribute values
🔍 Easy Querying - Filter models by EAV attributes with fluent API
🌍 Translatable - Support for multi-language attribute names
📦 Zero Configuration - Works out of the box with sensible defaults
🚀 Performance Optimized - Efficient queries with eager loading support
Installation
Install the package via Composer:
composer require abdylreshit/laravel-eav
The package will auto-discover and register its service provider.
Configuration
Publish the migration:
php artisan vendor:publish --provider="Abdylreshit\LaravelEav\Providers\LaravelEavServiceProvider" --tag="migrations"
Run the migration:
php artisan migrate
This creates the necessary tables: attributes and attribute_values.
Quick Start
1. Add the Trait to Your Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Abdylreshit\LaravelEav\Traits\HasEavAttributes;
class Product extends Model
{
use HasEavAttributes;
}
2. Create Attributes
use Abdylreshit\LaravelEav\Models\Attribute;
use Abdylreshit\LaravelEav\Enums\AttributeType;
// Create a color attribute
Attribute::create([
'name' => 'Color',
'code' => 'color',
'type' => AttributeType::STRING,
]);
// Create a price attribute
Attribute::create([
'name' => 'Price',
'code' => 'price',
'type' => AttributeType::DECIMAL,
]);
3. Use Attributes on Your Model
$product = Product::find(1);
// Set a single attribute
$product->setAttribute('color', 'red');
// Set multiple attributes
$product->setAttributes([
'color' => 'blue',
'price' => 99.99,
'in_stock' => true,
]);
// Get an attribute
$color = $product->getAttribute('color'); // 'blue'
// Get multiple attributes
$attrs = $product->getAttributes(['color', 'price']);
// Get all attributes
$allAttrs = $product->getAllAttributes();
// Check if attribute exists
if ($product->hasAttribute('color')) {
// ...
}
// Delete an attribute
$product->deleteAttribute('color');
Querying with Attributes
Filter models by attribute values:
// Find products with a specific color
$redProducts = Product::whereAttribute('color', 'red')->get();
// Find products by multiple attributes
$products = Product::whereAttributes([
'color' => 'blue',
'in_stock' => true,
])->get();
// Combine with other queries
$products = Product::where('category_id', 1)
->whereAttribute('price', '>', 50)
->get();
Attribute Types
The package supports the following attribute types:
| Type | Description | Column |
|---|---|---|
| STRING | Short text | string_value |
| TEXT | Long text | text_value |
| INTEGER | Whole numbers | integer_value |
| DECIMAL | Decimal numbers | decimal_value |
| BOOLEAN | True/false | boolean_value |
| DATE | Date (Y-m-d) | date_value |
| DATETIME | DateTime (Y-m-d H:i:s) | datetime_value |
| JSON | JSON data | json_value |
| IMAGE | Image file | image_value |
| FILE | File attachment | file_value |
Define Attribute Type
use Abdylreshit\LaravelEav\Enums\AttributeType;
Attribute::create([
'name' => 'Description',
'code' => 'description',
'type' => AttributeType::TEXT,
]);
Attribute::create([
'name' => 'Launch Date',
'code' => 'launch_date',
'type' => AttributeType::DATETIME,
]);
Translatable Attributes
Attribute names are translatable out of the box:
$attribute = Attribute::create([
'name' => ['en' => 'Color', 'fr' => 'Couleur'],
'code' => 'color',
'type' => AttributeType::STRING,
]);
// Get the name in a specific language
$nameEn = $attribute->getTranslation('name', 'en'); // 'Color'
$nameFr = $attribute->getTranslation('name', 'fr'); // 'Couleur'
Eager Loading
Eager load EAV values with your model to avoid N+1 queries:
// Eager load all EAV values
$products = Product::with('eavValues.attribute')->get();
foreach ($products as $product) {
$color = $product->getAttribute('color'); // No additional query
}
Validation
Validate EAV attributes in your request:
use Abdylreshit\LaravelEav\Models\Attribute;
$validated = $request->validate([
'name' => 'required|string',
'color' => 'nullable|string|max:50',
'price' => 'nullable|numeric|min:0',
]);
$product = Product::create($validated);
$product->setAttributes($validated);
Available Methods
Getting Attributes
getAttribute(string $code)- Get a single attribute valuegetAttributes(array $codes)- Get multiple attribute valuesgetAllAttributes()- Get all attributes as an arrayhasAttribute(string $code)- Check if attribute exists
Setting Attributes
setAttribute(string $code, $value)- Set a single attributesetAttributes(array $attributes)- Set multiple attributes
Deleting Attributes
deleteAttribute(string $code)- Delete an attribute value
Querying
whereAttribute(string $code, $value)- Filter by single attributewhereAttributes(array $attributes)- Filter by multiple attributes
Relationships
eavValues()- MorphMany relationship to attribute values
Database Schema
Attributes Table
id - bigInteger, primary key
name - json, translatable attribute name
code - string, unique identifier
type - string, attribute type enum
created_at - timestamp
updated_at - timestamp
Attribute Values Table
id - bigInteger, primary key
attribute_id - bigInteger, foreign key to attributes
model_type - string, polymorphic model type
model_id - bigInteger, polymorphic model id
string_value - string, nullable
text_value - text, nullable
integer_value - integer, nullable
decimal_value - decimal(8,2), nullable
boolean_value - boolean, nullable
date_value - date, nullable
datetime_value - datetime, nullable
json_value - json, nullable
image_value - string, nullable
file_value - string, nullable
created_at - timestamp
updated_at - timestamp
Examples
E-Commerce Product Catalog
// Create attributes for a shoe product
Attribute::create(['name' => 'Size', 'code' => 'size', 'type' => AttributeType::STRING]);
Attribute::create(['name' => 'Color', 'code' => 'color', 'type' => AttributeType::STRING]);
Attribute::create(['name' => 'Material', 'code' => 'material', 'type' => AttributeType::STRING]);
// Set attributes on a product
$shoe = Product::find(1);
$shoe->setAttributes([
'size' => '42',
'color' => 'black',
'material' => 'leather',
]);
// Query products
$blackShoes = Product::whereAttribute('color', 'black')->get();
CMS Page Attributes
// Create attributes for a page
Attribute::create(['name' => 'Author', 'code' => 'author', 'type' => AttributeType::STRING]);
Attribute::create(['name' => 'SEO Title', 'code' => 'seo_title', 'type' => AttributeType::STRING]);
Attribute::create(['name' => 'Published Date', 'code' => 'published_date', 'type' => AttributeType::DATE]);
// Use on your Page model
$page = Page::find(1);
$page->setAttributes([
'author' => 'John Doe',
'seo_title' => 'Best Laravel Tips',
'published_date' => now()->format('Y-m-d'),
]);
Performance Tips
- Use Eager Loading - Always eager load EAV values when querying multiple models
- Index the code Column - Add a database index to
attributes.codefor faster queries - Cache Attributes - Cache commonly used attributes
- Batch Operations - Use batch setting/getting instead of individual calls
Console Commands
Publish Assets
php artisan eav:publish
Publishes migrations and configuration files.
Migrate EAV Tables
php artisan eav:migrate
Runs EAV-specific migrations.
Troubleshooting
Attribute Not Found
Ensure the attribute exists before setting a value:
$attribute = Attribute::where('code', 'color')->first();
if (!$attribute) {
Attribute::create([...]);
}
N+1 Query Problem
Use eager loading:
$products = Product::with('eavValues.attribute')->get();
Type Mismatch
Ensure the value type matches the attribute type:
$price = Attribute::where('code', 'price')->first();
// $price->type will be AttributeType::DECIMAL
// Always pass numeric values for decimal attributes
License
The Laravel EAV package is open-sourced software licensed under the MIT license.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For support, please open an issue on the GitHub repository.
Changelog
See CHANGELOG.md for recent changes.
Credits
Created by Abdylreshit
Made with ❤️ for Laravel developers