Skip to content

AuroraWebSoftware/FlexyField

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FlexyField

Because your models deserve superpowers 🦸

Build Status Latest Stable Version Total Downloads License


Ever wished you could add fields to your Laravel models without touching migrations?

Now you can. Welcome to FlexyField.

composer require aurorawebsoftware/flexyfield
php artisan migrate

The Magic ✨

// Give your model the power
class Product extends Model implements FlexyModelContract
{
    use Flexy;
}

// Create a schema (think of it as a "field template")
Product::createSchema('electronics', 'Electronics');
Product::addFieldToSchema('electronics', 'voltage', FlexyFieldType::STRING);
Product::addFieldToSchema('electronics', 'warranty_years', FlexyFieldType::INTEGER);

// Use it like it was always there
$tv = Product::create(['name' => 'Smart TV']);
$tv->assignToSchema('electronics');
$tv->flexy->voltage = '220V';
$tv->flexy->warranty_years = 2;
$tv->save();

// Query like a boss
Product::where('flexy_voltage', '220V')->get();

No migrations. No schema changes. Just vibes. πŸŽ‰

Why FlexyField?

Problem Old Way FlexyField Way
"We need a new product attribute" Migration + deploy + pray πŸ™ addFieldToSchema() βœ…
"Different products need different fields" JSON column chaos 😱 Schemas! 🎯
"Can we query by that custom field?" nervous laughter where('flexy_field', $value) 😎

Field Types

Type What it stores Example
STRING Text $m->flexy->color = 'blue'
INTEGER Whole numbers $m->flexy->stock = 42
DECIMAL Money, measurements $m->flexy->price = 99.99
BOOLEAN Yes/No $m->flexy->active = true
DATE Dates $m->flexy->release = '2024-01-01'
DATETIME Timestamps $m->flexy->created = now()
JSON Arrays, objects $m->flexy->tags = ['hot', 'new']
FILE Uploads $m->flexy->manual = $request->file('pdf')

Real-World Examples 🌍

E-Commerce (PIM Style)

// Shoes have sizes and colors
Product::createSchema('footwear', 'Footwear');
Product::addFieldToSchema('footwear', 'shoe_size', FlexyFieldType::INTEGER,
    validationRules: 'required|between:35,50');
Product::addFieldToSchema('footwear', 'color', FlexyFieldType::STRING,
    fieldMetadata: ['options' => ['black', 'white', 'red', 'blue']]);

// Books have ISBNs and authors
Product::createSchema('books', 'Books');
Product::addFieldToSchema('books', 'isbn', FlexyFieldType::STRING,
    validationRules: 'required|size:13');
Product::addFieldToSchema('books', 'author', FlexyFieldType::STRING);
Product::addFieldToSchema('books', 'pages', FlexyFieldType::INTEGER);

// Same model, different fields!
$sneakers = Product::create(['name' => 'Air Max']);
$sneakers->assignToSchema('footwear');
$sneakers->flexy->shoe_size = 42;
$sneakers->flexy->color = 'black';

$novel = Product::create(['name' => 'Clean Code']);
$novel->assignToSchema('books');
$novel->flexy->isbn = '9780132350884';
$novel->flexy->author = 'Robert C. Martin';

CRM (Customer Segments)

// B2B customers need company info
Contact::createSchema('b2b', 'Business Customers');
Contact::addFieldToSchema('b2b', 'company_name', FlexyFieldType::STRING);
Contact::addFieldToSchema('b2b', 'employee_count', FlexyFieldType::INTEGER);
Contact::addFieldToSchema('b2b', 'annual_revenue', FlexyFieldType::DECIMAL);

// B2C customers need personal preferences
Contact::createSchema('b2c', 'Individual Customers');
Contact::addFieldToSchema('b2c', 'birthday', FlexyFieldType::DATE);
Contact::addFieldToSchema('b2c', 'interests', FlexyFieldType::JSON,
    fieldMetadata: ['options' => ['tech', 'sports', 'music', 'travel'], 'multiple' => true]);

// Query by segment
$bigCompanies = Contact::whereSchema('b2b')
    ->where('flexy_annual_revenue', '>', 1000000)
    ->get();

Multi-tenant SaaS

// Each tenant can have custom fields!
$tenantSchema = "tenant_{$tenant->id}_leads";

Lead::createSchema($tenantSchema, "{$tenant->name} Leads");
Lead::addFieldToSchema($tenantSchema, 'source', FlexyFieldType::STRING);
Lead::addFieldToSchema($tenantSchema, 'score', FlexyFieldType::INTEGER);

// Tenant-specific fields added via admin panel
foreach ($tenant->customFields as $field) {
    Lead::addFieldToSchema($tenantSchema, $field->name, $field->type);
}

Cool Features 🎁

Dropdowns & Multi-select

// Single choice
Product::addFieldToSchema('schema', 'size', FlexyFieldType::STRING,
    fieldMetadata: ['options' => ['S', 'M', 'L', 'XL']]);

// Multiple choices (use JSON type!)
Product::addFieldToSchema('schema', 'features', FlexyFieldType::JSON,
    fieldMetadata: ['options' => ['wifi', 'bluetooth', '5g'], 'multiple' => true]);

$phone->flexy->size = 'M';
$phone->flexy->features = ['wifi', '5g'];  // Array!

File Uploads (with Security Baked In πŸ”’)

Product::addFieldToSchema('schema', 'manual', FlexyFieldType::FILE,
    validationRules: 'required|mimes:pdf|max:5120',
    fieldMetadata: ['disk' => 's3', 'allowed_extensions' => ['pdf']]);

$product->flexy->manual = $request->file('manual');
$product->save();

// Get URLs
$url = $product->getFlexyFileUrl('manual');
$signedUrl = $product->getFlexyFileUrlSigned('manual', now()->addHour()->timestamp);

Validation (Because Data Integrity Matters)

Product::addFieldToSchema('schema', 'email', FlexyFieldType::STRING,
    validationRules: 'required|email|max:255',
    validationMessages: ['email.email' => 'GeΓ§erli bir email girin!']);

$product->flexy->email = 'not-an-email';
$product->save();  // πŸ’₯ ValidationException!

UI Hints & Grouping

Product::addFieldToSchema('schema', 'battery', FlexyFieldType::INTEGER,
    label: 'Battery Capacity',
    fieldMetadata: [
        'group' => 'Technical Specs',
        'placeholder' => 'mAh',
        'hint' => 'Typical range: 3000-5000'
    ]);

// Perfect for building dynamic forms!
$schema->getFieldsGrouped();  // ['Technical Specs' => [...], 'Ungrouped' => [...]]

Querying πŸ”

// Simple
Product::where('flexy_color', 'blue')->get();

// Dynamic method (Laravel magic!)
Product::whereFlexyColor('blue')->get();

// By schema
Product::whereSchema('electronics')->get();
Product::whereSchemaIn(['electronics', 'furniture'])->get();

// Go wild
Product::whereSchema('electronics')
    ->where('flexy_price', '<', 100)
    ->where('flexy_active', true)
    ->orderBy('flexy_price')
    ->get();

Configuration βš™οΈ

Publish the config file:

php artisan vendor:publish --tag="flexyfield-config"
// config/flexyfield.php
return [
    'file_storage' => [
        'default_disk' => env('FLEXYFIELD_DEFAULT_DISK', 'public'),
        'default_path' => env('FLEXYFIELD_DEFAULT_PATH', 'flexyfield'),
        'path_structure' => '{model_type}/{schema_code}/{field_name}/{year}/{month}',
        'cleanup_on_delete' => true,      // Auto-delete files when model deleted
        'enable_security_logging' => true, // Log security events
    ],
];

Environment Variables:

FLEXYFIELD_DEFAULT_DISK=s3
FLEXYFIELD_DEFAULT_PATH=uploads/flexy
FLEXYFIELD_CLEANUP_DELETE=true
FLEXYFIELD_SECURITY_LOGGING=true

AI-Powered Development πŸ€–

FlexyField comes with Laravel Boost guidelines for AI agents!

resources/boost/guidelines/core.blade.php

Your AI assistant (Claude, GPT, Copilot) can read this file and instantly understand:

  • All API methods and signatures
  • Field types and metadata options
  • Common patterns and best practices
  • Error handling and exceptions

Just point your AI to the guideline file and watch it write perfect FlexyField code! 🎯

Don't Do This ❌

// Setting values before assigning schema
$product->flexy->field = 'x';  // πŸ’₯ Exception!

// Always assign first!
$product->assignToSchema('electronics');
$product->flexy->field = 'x';  // βœ…

// Wrong query syntax
Product::where('flexy->field', 'x');  // 🚫 Nope

// Use underscore prefix
Product::where('flexy_field', 'x');  // βœ… Yes!

Performance πŸš€

  • Smart view recreation - Only rebuilds when NEW fields are added
  • Scales well - Tested with 50+ fields, 1M+ records
  • Manual rebuild - php artisan flexyfield:rebuild-view

Requirements

  • PHP 8.2+
  • Laravel 11+
  • MySQL 8+ or PostgreSQL 16+

Documentation

Guide What's Inside
Performance Make it fly πŸš€
Best Practices Do it right βœ…
Deployment Ship it safely πŸ“¦
Troubleshooting Fix it fast πŸ”§
File Security Lock it down πŸ”’

Contributing

composer install
./vendor/bin/pest              # Run tests
./vendor/bin/phpstan analyse   # Static analysis
./vendor/bin/pint              # Code style

PRs welcome! 🀝

License

MIT - Go build something awesome! πŸš€


Made with β˜• by Aurora Web Software

⭐ Star us on GitHub!

About

Laravel FlexyField is useful package for dynamic model fields.

Resources

License

Stars

Watchers

Forks

Sponsor this project

Contributors 3

  •  
  •  
  •