ivanmercedes/flex-fields
Flex Fields lets you add dynamic custom fields to Laravel Eloquent models. Define field schemas, attach values to any model, and query them without extra migrations—ideal for user-defined metadata, CMS content, and configurable forms.
Architecture fit This package is a Filament plugin that layers a dynamic custom-field engine over Eloquent models: admins define fields, field groups, repeaters, and visibility/validation rules at runtime, and the package renders them into forms, tables, imports, and record history. Architecturally it sits between Filament’s form/table builders and the persistence layer, which is a natural fit for Laravel + Filament admin applications where the schema is expected to evolve without migrations. For teams already standardized on Filament, the fit is high; for teams on Nova, plain Blade, or API-only backends, the value proposition collapses because the plugin’s core surface is Filament UI components.
Integration feasibility
The 0.7.1 release is a narrow, low-friction bugfix. It corrects the active-field cache so fields are cached as plain attributes and rebuilt as models on read, avoiding a TypeError on newer Laravel applications where cache.serializable_classes prevents PHP class unserialization from cache. That is a compatibility fix for modern Laravel security defaults and should be adopted before enabling the package on new Laravel apps. Entries cached by older versions are rebuilt, which helps upgrades, but teams should still treat the field cache as part of the integration surface and verify cache behavior in the target environment. The prior 0.6.1 work—repeater key normalization and is_shown_in_list table rendering—remains relevant: it improved upgrade tolerance and table usability, but the ff_ normalization is still a compatibility shim rather than a data migration.
Technical risk
The dominant risk remains version maturity. At 0.7.1 the package is pre-1.0, so minor-version bumps may carry breaking changes and there is no long-term support guarantee. The 0.7.1 bug also surfaced a real operational dependency: active field definitions are cached, so cache configuration, invalidation, and multi-node consistency now matter to form reliability. The fix reduces the immediate TypeError risk on new Laravel apps, but stale or partially rebuilt cache entries remain a failure class to test. Second, the ff_ normalization indicates a data-format migration was handled in application code rather than in a database migration; until a backfill occurs, the read path and the write path are not symmetric, which complicates exports, raw SQL reporting, and any future extraction of the field engine. Third, a runtime-defined field system is effectively a schema inside a schema: query performance, indexing, and validation guarantees all depend on package internals, and debugging becomes a two-layer problem. Fourth, the reliance on Filament ties upgrade risk to Filament’s own release cadence, which historically includes breaking changes across major versions.
Key questions
ff_ keys, and if not, what is the deprecation horizon for the normalization path?cache.serializable_classes disabled?Stack fit Best suited to Laravel 10/11+ with Filament 3.x, PHP 8.2+, and MySQL/PostgreSQL. It assumes a conventional Eloquent model per record type and a Filament panel for administration. The field cache means the Laravel cache store is now an explicit integration concern; validate the production cache driver, eviction policy, and serialization settings. If the application also exposes a JSON API for mobile or third-party clients, the API layer must be taught the field schema independently—the package’s form rendering does not substitute for API-side validation, so plan for a parallel serialization contract. The API/import/AI-tool path is explicitly supported by the repeater fixes, which makes the package viable for headless ingestion workflows, not just manual admin entry.
Migration path
Adopt on a new or low-traffic model first. For existing installations on an earlier 0.x, upgrading to 0.7.1 is safe but should include a deliberate cache step: deploy, clear the relevant cache entries, and verify that record forms render for models with active custom fields. Schedule a backfill job that reads each record through the package’s normalizer and writes back declared keys, then verify counts and checksums before removing reliance on the shim. Do not attempt to migrate data manually—route it through the package so normalization logic stays authoritative. For teams moving off hand-rolled custom-field tables, export into the package’s expected shape with declared keys from day one rather than replaying ff_-prefixed payloads.
Compatibility
Verify the Filament constraint in composer.json against the version pinned in your panel, and check that any custom field types registered by your team extend the current base classes—the sub-field key change can affect custom repeater implementations that hardcoded the prefix. Confirm the Laravel version and cache configuration, particularly cache.serializable_classes; older package versions can fail with a TypeError on newer Laravel apps where class unserialization is disabled. Test with the production cache driver, not just the array driver, and confirm behavior when cache entries are evicted or rebuilt. Confirm that CSV import templates and any AI-tool field mappings emitted by older versions are regenerated against declared keys. Livewire version alignment matters as well, since form state hydration is where repeater and cached-field bugs surface.
Sequencing
is_shown_in_list on each field type (boolean, image, color, formatted text) and confirm searchability behavior matches expectations.Maintenance
Ongoing maintenance is moderate and concentrated in three areas: keeping the package aligned with Filament majors, owning the field schema as a product asset, and managing field-cache invalidation. The schema ownership point is underappreciated—once business users can create fields, someone must govern naming, duplication, orphaned fields, and the meaning of is_shown_in_list across dozens of records tables. Cache ownership is now equally concrete: field changes must reliably invalidate and rebuild cached active-field definitions. Assign both responsibilities before rollout, not after. The ff_ normalization is technical debt that should be tracked with a removal date.
Support Support load will come from admins, not developers. Expect tickets about fields not appearing in forms, columns missing from tables, import failures caused by mismatched keys, and—post-upgrade—forms failing after Laravel or cache configuration changes. Publish an internal runbook covering: how to inspect a stored field payload, how to check whether a field is searchable, how to clear/rebuild the field cache, and the escalation path when a repeater item or cached field does not render. The refreshed documentation with real screenshots shortens this considerably and is worth linking directly from internal docs.
Scaling Two scaling axes. Data volume: filtering and sorting on dynamically defined fields typically cannot rely on indexes, so record tables will degrade as row counts grow—establish a threshold (for example, a few hundred thousand records per model) beyond which custom fields are discouraged in favor of first-class columns. Schema volume: hundreds of fields across many groups makes forms slow to render and hard to reason about; impose a review gate on field creation. The field cache helps read performance but adds invalidation complexity, especially in multi-node deployments. Neither is a 0.7.1 regression, but the new table-column feature increases the temptation to surface many fields at once, which is exactly where table performance and cognitive load degrade first.
Failure modes
is_shown_in_list enabled on high-cardinality models cause slow table queries, particularly with searchable formatted-text columns.Ramp-up Developer ramp-up is roughly one to two days for a Laravel-fluent engineer familiar with Filament, plus a further day to understand the field-schema data model, the field cache, and where normalization happens. The main learning curve is not the API but the mental model: fields are data, so bugs may live in stored payloads or cache entries rather than code. Administrator ramp-up is short—under an hour with the new documentation—but should be paired with a governance briefing covering when to create a field versus when to request a real column. Budget one sprint for a first production model including cache verification, backfill, and validation, and treat the second model as the real test of whether the abstraction holds for your domain.
How can I help you explore Laravel packages today?