Populate Dynamic Filament Selects from Eloquent Without N+1 Queries or Data Leaks | FilaForms                                 [ ![Filaforms Logo](https://filaforms.app/logo.svg)FilaForms

 ](https://filaforms.app)  [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app/pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app)  [ Try Demo ](https://filaforms.app/login) [ Buy a license ](https://filaforms.app/pricing#plans) 

 [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app/pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app) [ Try Demo ](https://filaforms.app/login) [ Buy a license ](https://filaforms.app/pricing#plans) 

   ![FilaForms](https://filaforms.app/logo.svg) FilaForms 

 TutorialsPopulate Dynamic Filament Selects from Eloquent Without N+1 Queries or Data Leaks
=================================================================================

 filaforms.app/blog

  [    Back to blog ](https://filaforms.app/blog) [ Tutorials ](https://filaforms.app/blog/category/tutorials) 

Populate Dynamic Filament Selects from Eloquent Without N+1 Queries or Data Leaks
=================================================================================

 Manuk Minasyan ·  September 1, 2026  · 4 min read 

 `Product::pluck('name', 'id')` is convenient until the table has 100,000 rows, labels depend on relationships, or one tenant can guess another tenant's ID. A production option source has three jobs: search and display, authorization, and final validation.

Solving only the first job makes a dropdown look correct while leaving the submission boundary slow or unsafe.

Choose a loading strategy by cardinality
----------------------------------------

StrategyGood forFailure modeStatic options in the schemaTiny, rarely changing listsStale duplicated dataPreloaded Eloquent optionsBounded reference dataLarge HTML/Livewire payloadAsync searchable selectMedium/large indexed tablesPoor search query or missing scopeModal/table selectorComplex filters and rich recordsMore interaction and implementationFilament 5 supports scoped relationship queries, searchable columns, custom labels, and deliberate preloading. Its default searchable result limit is bounded for a reason. Review the [Filament Select documentation](https://filamentphp.com/docs/5.x/forms/select) before increasing it.

Store a source key, not a model class
-------------------------------------

For a database-driven form, avoid storing `App\\Models\\Product`, table names, columns, or closures in JSON. Store a reviewed identifier:

```
{
  "type": "select",
  "option_source": "active_products"
}

```

Application code owns the registry entry:

```
'active_products' => new OptionSource(
    query: fn (Tenant $tenant) => Product::query()
        ->whereBelongsTo($tenant)
        ->where('is_active', true)
        ->with('category'),
    searchColumns: ['name', 'sku'],
    value: fn (Product $product) => $product->getKey(),
    label: fn (Product $product) => "{$product->name} · {$product->category->name}",
),

```

Form authors select a capability. Developers own the query, scope, eager loads, value, label, and search columns.

Keep list and validation scopes identical
-----------------------------------------

The browser can submit any ID, including one that never appeared in the list. Revalidate the selected value with the same conditions:

- correct tenant or owner;
- active/selectable state;
- expected model type;
- dependent-field constraint;
- soft-delete policy.

Do not use a plain global `exists:products,id` when the list only showed one tenant's active products. Build the rule from the registered source or a dedicated custom rule so the query cannot drift.

This is especially important outside a Filament tenant panel. Panel resource scoping does not magically attach to every public route or raw Laravel validation rule.

Prevent N+1 label queries
-------------------------

Custom option labels often read relationships:

```
fn (Product $record) => $record->name.' — '.$record->category->name

```

Without eager loading, each label can query its category. Select only needed columns, eager-load label dependencies, and assert query counts in a feature test. Be careful that selecting a subset retains foreign keys required for the relationship.

For remote search, index the searched columns, require a minimum query length where useful, cap results, and avoid leading-wildcard searches on unindexed large datasets.

Dependent selects are server rules too
--------------------------------------

For country → city, the city source uses the selected country to narrow search. Treat the controlling Livewire value as untrusted. The final rule must prove both that the city is selectable and that it belongs to the submitted country.

The UI relationship is covered in our [conditional-fields guide](/blog/conditional-logic-in-laravel-forms-when-fields-should-show-and-hide); the database relationship must be enforced independently.

Cache with the entire security context
--------------------------------------

Option caching is useful for small shared references, but the cache key may need:

```
source + tenant + locale + search + dependencies + permission role

```

Leaving out tenant or locale can expose names across organizations or display labels in the wrong language. Short-lived caching does not make an unsafe key acceptable.

Preserve historical meaning
---------------------------

Store stable model keys, not labels, as submitted values. Then decide what an old submission should show if the record changes:

- current label for operational truth;
- label from its immutable form revision;
- label snapshot captured on submit.

Deleted or newly unauthorized records may remain readable in historical submissions without remaining selectable in new ones. That display path should never be reused as an active option query. [Form versioning](/blog/form-versioning-in-laravel-keep-old-submissions-readable-when-fields-change) explains why the selected ID alone is not enough for audit fidelity.

Measure instead of guessing
---------------------------

Benchmark at 50, 5,000, and 100,000 records. Record initial queries, query time, Livewire payload bytes, rendered option count, search latency, and browser responsiveness for:

- full `pluck()`;
- deliberate preload;
- async indexed search;
- custom relationship labels.

The [form performance guide](/blog/form-performance-laravel-loading-validation-submission-speed) gives a broader measurement model.

Failure tests worth keeping
---------------------------

- another tenant's ID is rejected even when guessed;
- an inactive ID that was previously valid cannot be newly selected;
- dependent IDs must belong to the controller value;
- label rendering has a bounded query count;
- a deleted option still renders according to the historical policy;
- caches cannot cross tenant or locale;
- huge datasets do not preload during initial render.

A dynamic select is not just a convenient query. Treat it as a server-owned data capability with separate display and validation paths, and it remains fast without becoming an authorization hole.

Stop rebuilding forms on every project.
---------------------------------------

 FilaForms gives your Laravel app a visual form builder, submissions, analytics, and notifications. One payment, self-hosted, no subscription.

 [ Buy from $49.50   ](https://filaforms.app/pricing#plans) [ Try Demo ](https://filaforms.app/login) 

 Related posts
-------------

 [  Tutorials   Aug 25, 2026  

 Form Versioning in Laravel: Keep Old Submissions Readable When Fields Change 
------------------------------------------------------------------------------

Design immutable Laravel form revisions so renamed fields, deleted options, drafts, and old submissions remain valid and readable.

 ](https://filaforms.app/blog/form-versioning-in-laravel-keep-old-submissions-readable-when-fields-change) [  Tutorials   Aug 18, 2026  

 Dynamic Form Validation in Laravel: Safely Storing Rules in the Database 
--------------------------------------------------------------------------

Compile database-stored Laravel form rules safely with allowlists, typed parameters, nested validation, tenant scopes, and adversarial tests.

 ](https://filaforms.app/blog/dynamic-form-validation-in-laravel-safely-storing-rules-in-the-database) [  Tutorials   Jul 28, 2026  

 Form Performance in Laravel: Loading, Validation, and Submission Speed 
------------------------------------------------------------------------

Form page loads in 2.8 seconds. INP is 380 ms. Submit lags. Conversion drops and you feel it but can't see why. Here's the five-number checklist that finds the leak.

 ](https://filaforms.app/blog/form-performance-laravel-loading-validation-submission-speed) 

    ![FilaForms Logo](/logo.svg) FilaForms 

 Laravel form infrastructure for Filament. Stop rebuilding forms on every project.

 [ Buy a license   ](https://filaforms.app/pricing#plans) 

 ### Product

 [ Features ](https://filaforms.app#features) [ Documentation ](https://docs.filaforms.app) [ Blog ](https://filaforms.app/blog) [ Pricing ](https://filaforms.app/pricing) [ About ](https://filaforms.app/about) [ Contact ](mailto:hello@filaforms.app) 

 ### Legal

 [ Terms of Service ](https://filaforms.app/terms-of-service) [ Privacy Policy ](https://filaforms.app/privacy-policy) 

  © 2025-2026 FilaForms. All rights reserved.

 [    ](mailto:hello@filaforms.app) [    ](https://x.com/MinasyanManuk)
