Overriding Models
The Custom Fields package allows you to replace the default models with your own implementations.
Registering Custom Models
Register your custom models using the CustomFields class:
use Relaticle\CustomFields\CustomFields;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
CustomFields::useCustomFieldModel(YourCustomField::class);
CustomFields::useValueModel(YourCustomFieldValue::class);
CustomFields::useOptionModel(YourCustomFieldOption::class);
CustomFields::useSectionModel(YourCustomFieldSection::class);
}
}
Configuration File
The configuration file (config/custom-fields.php) allows you to customize all aspects of the Custom Fields package. It uses modern fluent configurators for type safety and better IDE support.
Entity Configuration
Configure which models can have custom fields:
'entity_configuration' => EntityConfigurator::configure()
->discover(app_path('Models')) // Auto-discover models in this path
->cache(true), // Enable caching for performance
Field Types Configuration
Control which field types are available:
'field_type_configuration' => FieldTypeConfigurator::configure()
->enabled([]) // Empty = all enabled
->disabled(['file-upload']) // Disable specific field types
->discover(true) // Auto-discover custom field types
->cache(enabled: false, ttl: 3400),
Features Configuration
Configure package features using the enum-based system:
'features' => FeatureConfigurator::configure()
->enable(
CustomFieldsFeature::FIELD_CONDITIONAL_VISIBILITY,
CustomFieldsFeature::FIELD_ENCRYPTION,
CustomFieldsFeature::FIELD_OPTION_COLORS,
CustomFieldsFeature::UI_TABLE_COLUMNS,
CustomFieldsFeature::UI_TOGGLEABLE_COLUMNS,
CustomFieldsFeature::UI_TABLE_FILTERS,
CustomFieldsFeature::SYSTEM_MANAGEMENT_INTERFACE
)
->disable(
CustomFieldsFeature::SYSTEM_MULTI_TENANCY
),
Management Interface
Configure the custom fields management page:
'management' => [
'slug' => 'custom-fields', // URL slug
'navigation_sort' => -1, // Navigation sort order
'navigation_group' => true, // Group in navigation
'cluster' => null, // Optional cluster assignment
],
Database Configuration
Customize table names and paths:
'database' => [
'migrations_path' => database_path('custom-fields'),
'table_names' => [
'custom_field_sections' => 'custom_field_sections',
'custom_fields' => 'custom_fields',
'custom_field_values' => 'custom_field_values',
'custom_field_options' => 'custom_field_options',
],
'column_names' => [
'tenant_foreign_key' => 'tenant_id',
],
],
Available Features
The package supports these features that can be enabled/disabled:
| Feature | Description |
|---|
FIELD_CONDITIONAL_VISIBILITY | Show/hide fields based on conditions |
FIELD_ENCRYPTION | Encrypt sensitive field values |
FIELD_OPTION_COLORS | Color-coded options for select fields |
UI_TABLE_COLUMNS | Show custom fields as table columns |
UI_TOGGLEABLE_COLUMNS | Allow users to toggle column visibility |
UI_TABLE_FILTERS | Enable filtering by custom field values |
SYSTEM_MANAGEMENT_INTERFACE | Enable the management interface |
SYSTEM_MULTI_TENANCY | Enable multi-tenant isolation |
Overriding Models
The Custom Fields package allows you to replace the default models with your own implementations.
Registering Custom Models
Register your custom models using the CustomFields class:
use Relaticle\CustomFields\CustomFields;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
CustomFields::useCustomFieldModel(YourCustomField::class);
CustomFields::useValueModel(YourCustomFieldValue::class);
CustomFields::useOptionModel(YourCustomFieldOption::class);
CustomFields::useSectionModel(YourCustomFieldSection::class);
}
}
If your custom models include tenant-specific scoping logic, you’ll need to register a custom tenant resolver to ensure validation works correctly.
Configuration Examples
Restricting Field Types
Limit available field types in production:
'field_type_configuration' => FieldTypeConfigurator::configure()
->enabled([
'text',
'textarea',
'number',
'select',
'checkbox',
'date',
])
->disabled([
'rich-editor', // Disable rich content editors
'markdown-editor', // Disable markdown editor
'file-upload', // Disable file uploads
]),
Optimize for production:
'entity_configuration' => EntityConfigurator::configure()
->discover(app_path('Models'))
->cache(env('CUSTOM_FIELDS_CACHE', true)), // Enable caching
'field_type_configuration' => FieldTypeConfigurator::configure()
->cache(enabled: true, ttl: 3600), // Cache field types
Multi-Tenancy Setup
Enable tenant isolation:
'features' => FeatureConfigurator::configure()
->enable(
CustomFieldsFeature::SYSTEM_MULTI_TENANCY,
// ... other features
),
'database' => [
// ... other config
'column_names' => [
'tenant_foreign_key' => 'tenant_id', // Your tenant foreign key
],
],
Custom Tenant Resolution
If you’ve extended the CustomField or CustomFieldSection models with custom tenant handling (e.g., custom global scopes), register a tenant resolver to ensure validation and queries respect your custom logic:
use Relaticle\CustomFields\CustomFields;
// In your AppServiceProvider or plugin boot method
CustomFields::resolveTenantUsing(fn() => auth()->user()?->company_id);
The custom resolver takes priority over Filament’s built-in tenancy, giving you complete control over tenant resolution.
Common Patterns:
// Auth-based tenancy
CustomFields::resolveTenantUsing(fn() => auth()->user()?->company_id);
// Header-based (APIs)
CustomFields::resolveTenantUsing(fn() => request()->header('X-Tenant-ID'));
// Session-based
CustomFields::resolveTenantUsing(fn() => session('current_tenant_id'));
Need help? Check that your resolver returns the correct tenant ID using TenantContextService::getCurrentTenantId() in your application.
Best Practices
- Enable Caching: Always enable caching in production
- Limit Discovery: Only discover models you need
- Restrict Field Types: Only enable field types you use
Security Considerations
- Disable Unused Features: Turn off features you don’t need
- Restrict Field Types: Disable potentially unsafe field types like rich editors
- Enable Multi-Tenancy: Always enable in multi-tenant applications
Development vs Production
Use environment variables for flexible configuration:
'entity_configuration' => EntityConfigurator::configure()
->discover(app_path('Models'))
->cache(env('CUSTOM_FIELDS_CACHE', !app()->isLocal())),
'field_type_configuration' => FieldTypeConfigurator::configure()
->cache(enabled: env('CUSTOM_FIELDS_CACHE_TYPES', true)),