Conversation
Add two new feature-flagged capabilities: 1. Model attribute conditions: visibility conditions can now reference the parent model's database columns (e.g., show field when product.type === 'physical'), not just other custom field values. 2. Section-level visibility: sections support the same conditional visibility system as fields, with full parity for both custom field and model attribute conditions. Key changes: - New ConditionSource enum (CustomField / ModelAttribute) - ModelAttributeDiscoveryService for introspecting model columns - VisibilityData and CoreVisibilityLogicService accept optional Model - FrontendVisibilityService generates $get() paths per source type - SectionComponentFactory applies visibleJs for reactive visibility - VisibilityComponent admin UI with source selector and dynamic inputs - Fix visibleJs/visible() conflict that prevented reactive visibility
Widen filament constraint from ^5.0 to ^4.0|^5.0 since Filament v5 has no API changes over v4 (only Livewire v4 compat bump).
There was a problem hiding this comment.
Pull request overview
This pull request adds support for model attribute conditions in visibility rules and enables section-level conditional visibility, while also introducing compatibility with Filament v4 alongside existing v5 support.
Changes:
- Introduces model attribute conditions allowing visibility rules to reference model properties directly (not just custom fields)
- Adds section conditional visibility feature with frontend (JavaScript) and backend (PHP) evaluation
- Adds backward compatibility with Filament v4 by updating the composer dependency constraint from
^5.0to^4.0|^5.0
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Enums/ConditionSource.php | New enum defining CustomField and ModelAttribute as condition sources |
| src/Enums/CustomFieldsFeature.php | Adds MODEL_ATTRIBUTE_CONDITIONS and SECTION_CONDITIONAL_VISIBILITY feature flags |
| src/Data/VisibilityConditionData.php | Adds source field with CustomField default for backward compatibility |
| src/Data/VisibilityData.php | Updates evaluate() to accept Model record for model attribute evaluation |
| src/Data/CustomFieldSectionSettingsData.php | Adds visibility property to support section-level visibility configuration |
| src/Services/ModelAttributeDiscoveryService.php | New service to discover and map model attributes for use in visibility conditions |
| src/Services/Visibility/CoreVisibilityLogicService.php | Extends to support section visibility and model record parameter |
| src/Services/Visibility/BackendVisibilityService.php | Adds isSectionVisible method for server-side section visibility evaluation |
| src/Services/Visibility/FrontendVisibilityService.php | Adds buildSectionVisibilityExpression for client-side JS generation |
| src/Filament/Integration/Factories/SectionComponentFactory.php | Applies visibility logic to section components using visibleJs |
| src/Filament/Integration/Base/AbstractFormComponent.php | Updated visibility application pattern |
| src/Filament/Integration/Builders/FormBuilder.php | Passes record to section factory for visibility evaluation |
| src/Filament/Management/Forms/Components/VisibilityComponent.php | Adds UI for selecting condition source and model attributes |
| src/Filament/Management/Schemas/SectionForm.php | Integrates visibility component into section form |
| src/Livewire/ManageCustomFieldSection.php | Adjusts modal sizing based on visibility feature |
| src/Filament/Management/Pages/CustomFieldsManagementPage.php | Adjusts modal sizing for section creation |
| composer.json | Updates Filament constraint to support both v4 and v5 |
| tests/Feature/SectionVisibilityIntegrationTest.php | Comprehensive integration tests for section visibility |
| tests/Feature/ModelAttributeConditionsTest.php | Comprehensive unit tests for model attribute conditions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| class CustomFieldSectionSettingsData extends Data | ||
| { | ||
| public function __construct( | ||
| public VisibilityData $visibility = new VisibilityData, |
There was a problem hiding this comment.
Using new VisibilityData as a default parameter value may cause issues with Spatie Laravel Data. When deserializing data, this creates a new instance that might not match the expected serialization format. Consider using ?VisibilityData $visibility = null instead, or remove the default value entirely and handle null cases where this property is accessed.
| public VisibilityData $visibility = new VisibilityData, | |
| public ?VisibilityData $visibility = null, |
| "require": { | ||
| "php": "^8.3", | ||
| "filament/filament": "^5.0", | ||
| "filament/filament": "^4.0|^5.0", |
There was a problem hiding this comment.
The Filament version constraint change from "^5.0" to "^4.0|^5.0" introduces backward compatibility with Filament v4. This is a significant change that should be thoroughly tested to ensure all features work correctly in both v4 and v5. Consider documenting any known differences or limitations when running on v4 vs v5.
| "filament/filament": "^4.0|^5.0", | |
| "filament/filament": "^5.0", |
| return new $modelClass; | ||
| } | ||
|
|
||
| if (class_exists($entityType) && is_subclass_of($entityType, Model::class)) { | ||
| return new $entityType; | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** |
There was a problem hiding this comment.
Instantiating models with new $modelClass (line 125) and new $entityType (line 129) may trigger unwanted side effects if the model has boot methods, observers, or global scopes. Consider using new $modelClass() without calling constructors or database interactions, or document that model instantiation is intentional and required for discovering table schema information.
| return new $modelClass; | |
| } | |
| if (class_exists($entityType) && is_subclass_of($entityType, Model::class)) { | |
| return new $entityType; | |
| } | |
| return null; | |
| } | |
| /** | |
| $model = $this->instantiateModel($modelClass); | |
| if ($model !== null) { | |
| return $model; | |
| } | |
| } | |
| if (class_exists($entityType) && is_subclass_of($entityType, Model::class)) { | |
| $model = $this->instantiateModel($entityType); | |
| if ($model !== null) { | |
| return $model; | |
| } | |
| } | |
| return null; | |
| } | |
| /** | |
| * Instantiate an Eloquent model without running its constructor or boot logic. | |
| */ | |
| private function instantiateModel(string $class): ?Model | |
| { | |
| if (!is_subclass_of($class, Model::class)) { | |
| return null; | |
| } | |
| try { | |
| $reflection = new \ReflectionClass($class); | |
| if ($reflection->isAbstract()) { | |
| return null; | |
| } | |
| /** @var Model $model */ | |
| $model = $reflection->newInstanceWithoutConstructor(); | |
| return $model; | |
| } catch (\ReflectionException $e) { | |
| return null; | |
| } | |
| } | |
| /** |
Remove redundant _ENABLED suffix for consistency with other SYSTEM_* feature names.
No description provided.