aurorawebsoftware / flexyfield
Laravel Models are now Uber Flexy!
Fund package maintenance!
AuroraWebSoftware
Installs: 963
Dependents: 1
Suggesters: 0
Security: 0
Stars: 23
Watchers: 1
Forks: 2
Open Issues: 0
pkg:composer/aurorawebsoftware/flexyfield
Requires
- php: ^8.2|^8.3|^8.4
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3
- laravel/pint: ^1.14
- nunomaduro/collision: ^8
- orchestra/testbench: ^10.0||^9.0.0
- pestphp/pest: ^3
- pestphp/pest-plugin-arch: ^3
- pestphp/pest-plugin-laravel: ^3
- phpstan/extension-installer: ^1
- phpstan/phpstan-deprecation-rules: ^2
- phpstan/phpstan-phpunit: ^2
This package is auto-updated.
Last update: 2025-12-01 12:24:12 UTC
README
Add dynamic fields to Laravel models without database migrations
FlexyField enables flexible, type-safe field management for Eloquent models. Perfect for e-commerce catalogs, multi-tenant apps, and CMS platforms where different model instances need different attributes.
โจ Features
- ๐ฏ Schema-Based Organization - Different instances can use different field configurations
- ๐ Type-Safe Storage - STRING, INTEGER, DECIMAL, DATE, DATETIME, BOOLEAN, JSON
- โ Built-in Validation - Laravel validation rules per schema
- ๐ Eloquent Integration - Query flexy fields with standard
where()methods - โก Performance Optimized - Smart view recreation (98% faster in v2.0)
- ๐ฆ Zero Migrations - Add fields without changing database schema
๐ Why FlexyField?
| Feature | FlexyField | JSON Columns | Custom Tables |
|---|---|---|---|
| Type Safety | โ Separate typed columns | โ Everything is JSON | โ Yes |
| Validation | โ Per-field rules | โ ๏ธ Manual | โ Yes |
| Queryable | โ Standard Eloquent | โ ๏ธ JSON queries | โ Yes |
| No Migrations | โ Add fields anytime | โ Yes | โ Requires migrations |
| Multiple Schemas | โ Per instance | โ No | โ No |
Perfect for:
- E-commerce (shoes need size/color, books need ISBN/author)
- Multi-tenant apps (different fields per tenant)
- CMS platforms (flexible content types)
- Dynamic forms and configurations
๐ฆ Installation
Requirements: PHP 8.2+, Laravel 11.x+, MySQL 8.0+ / PostgreSQL 16+
composer require aurorawebsoftware/flexyfield php artisan migrate
๐ฏ Quick Start
1. Enable on Model
use AuroraWebSoftware\FlexyField\Contracts\FlexyModelContract; use AuroraWebSoftware\FlexyField\Traits\Flexy; class Product extends Model implements FlexyModelContract { use Flexy; }
2. Create Schema & Fields
use AuroraWebSoftware\FlexyField\Enums\FlexyFieldType; // Create schema Product::createSchema('footwear', 'Footwear Products', isDefault: true); // Add validated fields Product::addFieldToSchema('footwear', 'size', FlexyFieldType::INTEGER, validationRules: 'required|numeric|min:20|max:50'); Product::addFieldToSchema('footwear', 'color', FlexyFieldType::STRING, validationRules: 'required|string|max:50');
3. Use Flexy Fields
$product = Product::create(['name' => 'Running Shoes']); $product->assignToSchema('footwear'); // Set values $product->flexy->size = 42; $product->flexy->color = 'blue'; $product->flexy->price = 49.90; $product->save(); // Query $blueShoes = Product::where('flexy_color', 'blue')->get(); $affordable = Product::where('flexy_price', '<', 100)->get();
๐ E-Commerce Example
Here is a practical example of how to use FlexyField in an e-commerce application with Category, Product, and Order models.
1. Setup Models
use AuroraWebSoftware\FlexyField\Contracts\FlexyModelContract; use AuroraWebSoftware\FlexyField\Traits\Flexy; use Illuminate\Database\Eloquent\Model; class Category extends Model implements FlexyModelContract { use Flexy; } class Product extends Model implements FlexyModelContract { use Flexy; } class Order extends Model implements FlexyModelContract { use Flexy; }
2. Define Schemas & Fields
use AuroraWebSoftware\FlexyField\Enums\FlexyFieldType; // --- Category Schema --- Category::createSchema('electronics', 'Electronics'); Category::addFieldToSchema('electronics', 'icon_class', FlexyFieldType::STRING); Category::addFieldToSchema('electronics', 'banner_color', FlexyFieldType::STRING); // --- Product Schema --- Product::createSchema('smartphone', 'Smartphone'); Product::addFieldToSchema('smartphone', 'screen_size', FlexyFieldType::DECIMAL); Product::addFieldToSchema('smartphone', 'battery_capacity', FlexyFieldType::INTEGER); Product::addFieldToSchema('smartphone', 'has_5g', FlexyFieldType::BOOLEAN); Product::addFieldToSchema('smartphone', 'release_date', FlexyFieldType::DATE); // --- Order Schema --- Order::createSchema('gift_order', 'Gift Order'); Order::addFieldToSchema('gift_order', 'gift_note', FlexyFieldType::STRING); Order::addFieldToSchema('gift_order', 'is_wrapped', FlexyFieldType::BOOLEAN); Order::addFieldToSchema('gift_order', 'delivery_instructions', FlexyFieldType::STRING);
3. Usage in Controller
// Create a Category with custom attributes $category = Category::create(['name' => 'Smartphones']); $category->assignToSchema('electronics'); $category->flexy->icon_class = 'fa-mobile'; $category->flexy->banner_color = '#FF5733'; $category->save(); // Create a Product with specific specs $product = Product::create(['name' => 'iPhone 15', 'category_id' => $category->id]); $product->assignToSchema('smartphone'); $product->flexy->screen_size = 6.1; $product->flexy->battery_capacity = 3349; $product->flexy->has_5g = true; $product->flexy->release_date = '2023-09-22'; $product->save(); // Create an Order with special instructions $order = Order::create(['user_id' => 1, 'total' => 999.99]); $order->assignToSchema('gift_order'); $order->flexy->gift_note = 'Happy Birthday!'; $order->flexy->is_wrapped = true; $order->save();
4. Querying
// Find all 5G smartphones released after 2023 $modernPhones = Product::whereSchema('smartphone') ->where('flexy_has_5g', true) ->where('flexy_release_date', '>=', '2023-01-01') ->get(); // Find all gift orders that need wrapping $ordersToWrap = Order::whereSchema('gift_order') ->where('flexy_is_wrapped', true) ->get();
๐ Documentation
- Performance Guide - Optimization, indexing, scaling (v2.0: 98% faster!)
- Best Practices - Patterns, validation, common pitfalls
- Deployment Guide - Production deployment, rollback, monitoring
- Troubleshooting - Common issues & solutions
Quick Troubleshooting:
- Field not found? โ
$model->assignToSchema('schema_code') - Validation errors? โ
Product::getFieldsForSchema('schema_code') - Slow queries? โ See Performance Guide
- View out of sync? โ
php artisan flexyfield:rebuild-view
โก Performance
v2.0 Smart View Recreation:
- Only recreates database view when NEW fields are added
- 1000 saves = 1-2 view recreations (vs 1000 in v1.0)
- ~98% performance improvement
Recommended Scale:
- โ Small: 1-20 fields, <100K models (Excellent)
- โ Medium: 20-50 fields, 100K-1M models (Good)
- โ ๏ธ Large: 50-100 fields, 1M-10M models (Acceptable with optimization)
๐ง Advanced Features
Multiple Schemas
// Footwear schema Product::createSchema('footwear', 'Footwear'); Product::addFieldToSchema('footwear', 'size', FlexyFieldType::INTEGER); // Books schema Product::createSchema('books', 'Books'); Product::addFieldToSchema('books', 'isbn', FlexyFieldType::STRING); // Query by schema $shoes = Product::whereSchema('footwear')->get();
Field Types
$product->flexy->name = 'Product'; // STRING $product->flexy->quantity = 100; // INTEGER $product->flexy->price = 49.90; // DECIMAL $product->flexy->in_stock = true; // BOOLEAN $product->flexy->published_at = Carbon::now(); // DATETIME $product->flexy->tags = ['summer', 'sale']; // JSON
Select Options
Restrict field values to predefined options:
use AuroraWebSoftware\FlexyField\Enums\FlexyFieldType; // Single select (dropdown) Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'color', fieldType: FlexyFieldType::STRING, fieldMetadata: ['options' => ['red' => 'Red', 'blue' => 'Blue', 'green' => 'Green']] ); // Multi-select (checkboxes) Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'features', fieldType: FlexyFieldType::JSON, fieldMetadata: [ 'options' => ['wifi', '5g', 'nfc', 'bluetooth'], 'multiple' => true ] ); // Usage $phone = Product::create(['name' => 'Smartphone']); $phone->assignToSchema('electronics'); $phone->flexy->color = 'blue'; // Single value $phone->flexy->features = ['wifi', '5g']; // Multiple values $phone->save();
Attribute Grouping
Organize related fields into groups for better UI presentation:
use AuroraWebSoftware\FlexyField\Models\FieldSchema; // Define fields with groups Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'voltage', fieldType: FlexyFieldType::STRING, fieldMetadata: ['group' => 'Power Specs'] ); Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'weight_kg', fieldType: FlexyFieldType::DECIMAL, fieldMetadata: ['group' => 'Physical Dimensions'] ); // Fields without group metadata are ungrouped Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'name', fieldType: FlexyFieldType::STRING ); // Retrieve fields organized by group $schema = FieldSchema::where('schema_code', 'electronics')->first(); $grouped = $schema->getFieldsGrouped(); // Iterate through groups foreach ($grouped as $groupName => $fields) { echo "Group: $groupName\n"; foreach ($fields as $field) { echo " - {$field->name}\n"; } }
UI Hints
Improve UX with human-readable labels, placeholders, and hints:
use AuroraWebSoftware\FlexyField\Models\SchemaField; // Define field with UI hints Product::addFieldToSchema( schemaCode: 'electronics', fieldName: 'battery_capacity_mah', fieldType: FlexyFieldType::INTEGER, label: 'Battery Capacity', fieldMetadata: [ 'placeholder' => 'Enter value in mAh', 'hint' => 'Typical range: 1000-5000mAh' ] ); // Retrieve UI hints $field = SchemaField::where('name', 'battery_capacity_mah')->first(); echo $field->getLabel(); // "Battery Capacity" echo $field->getPlaceholder(); // "Enter value in mAh" echo $field->getHint(); // "Typical range: 1000-5000mAh" // Label falls back to name if null $field->label = null; echo $field->getLabel(); // "battery_capacity_mah"
try { $product->flexy->size = 'invalid'; $product->save(); // Throws ValidationException } catch (ValidationException $e) { $errors = $e->errors(); }
๐งช Testing
./vendor/bin/pest # All tests ./vendor/bin/pest --coverage # With coverage ./vendor/bin/phpstan analyse # Static analysis ./vendor/bin/pint # Code style
๐ค Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Development:
composer install
docker-compose up -d
composer test
๐ License
MIT License. See LICENSE.md.
โญ Star this repo if you find it helpful!