Entity-Attribute-Value (EAV) Pattern
The Entity-Attribute-Value (EAV) pattern is a data model used when you need to store flexible, schema-less data — especially when the number or types of attributes vary widely between records. In Laravel, this can be implemented using multiple related tables.
🔧 Typical EAV Structure in Laravel
You usually have three main tables:
Entities – The main item (e.g., Product, User, etc.)
Attributes – Defines the possible attributes (e.g., color, size, weight)
Values – Stores the value of a specific attribute for a specific entity
🧱 Example: Product EAV
1. products table (Entities)
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
2. attributes table
Schema::create('attributes', function (Blueprint $table) {
$table->id();
$table->string('name'); // e.g., "Color", "Size"
$table->string('data_type'); // e.g., "string", "integer"
$table->timestamps();
});
3. attribute_values table (Values)
Schema::create('attribute_values', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id')->constrained('products')->onDelete('cascade');
$table->foreignId('attribute_id')->constrained('attributes')->onDelete('cascade');
$table->text('value'); // Store all values as string and cast later
$table->timestamps();
});
🔁 Eloquent Models & Relationships
Product.php
public function attributes()
{
return $this->hasMany(AttributeValue::class);
}
AttributeValue.php
public function product()
{
return $this->belongsTo(Product::class);
}
public function attribute()
{
return $this->belongsTo(Attribute::class);
}
Attribute.php
public function values()
{
return $this->hasMany(AttributeValue::class);
}
✅ Pros
Flexible — easily add new attributes without changing schema
Useful for dynamic forms, CMSs, or products with varying specs
❌ Cons
Complex queries (especially filtering/sorting)
Performance issues on large data sets
Not ideal for frequently queried attributes
🧠 Tip
To reduce complexity and improve performance:
Cache commonly used attributes
Use JSON columns if EAV is overkill and you’re using MySQL 5.7+ or PostgreSQL