Lookups
CommunityHierarchical lookup management for Filament with configurable multi-tenant support. Manage lookup tables (countries, categories, regions, statuses, etc.) with optional parent-child hierarchies. Each lookup type is defined as a PHP class with full control over permissions and behavior.
Author:
Mustafa Khaled
Package health
BetaAutomated checks of this plugin's Composer package
15 checks
- Skipped: GitHub Actions pinned to SHA
- Skipped: GitLab CI includes pinned to SHA
- Passed: Open security advisories
- Passed: Dependabot PR responsiveness — No open Dependabot PRs.
- Skipped: Renovate MR responsiveness
- Skipped: Dependabot or Renovate configured
- Skipped: Dependency update cooldown configured
- Failed: Provides a security policy — View details on Plumb
- Passed: Abandoned or archived — No consulted source marks the package abandoned (packagist, github).
- Passed: Commit and release recency — Active: last commit 101 days ago; last release 101 days ago.
-
Passed:
composer.lock not committed by library
—
composer.lockis absent from the released dist archive. - Passed: Dist archive is lean
-
Passed:
Current Laravel version supported
—
Package dependencies resolve together with current Laravel
13.0. -
Passed:
Current PHP version supported
—
Constraint
^8.2supports current PHP8.5. - Skipped: Current Symfony version supported
filament/
namespace. Review the source and install at your own risk. Found
malware or an unresolved security issue the author won't
address?
Report it
.
Documentation
- Installation
- Defining Lookup Types
- Available Lookup Methods
- Per-Record Permissions
- Using LookupSelect in Forms
- Using LookupService Programmatically
- Multi-Tenancy
- Configuration
- Plugin Configuration
- License
Hierarchical lookup management for Filament with configurable multi-tenant support.
Manage lookup tables (countries, categories, regions, statuses, etc.) with optional parent-child hierarchies. Each lookup type is defined as a PHP class with full control over permissions and behavior.
#Installation
composer require wezlo/filament-lookups
Run migrations:
php artisan migrate
Register the plugin in your panel provider:
use Wezlo\FilamentLookups\FilamentLookupsPlugin;
$panel
->plugin(FilamentLookupsPlugin::make()
->navigationGroup('Settings'));
#Defining Lookup Types
Each lookup type is a PHP class that extends Lookup. Create them with the artisan command and sync to the database.
#1. Create a Lookup class
php artisan make:lookup Countries
php artisan make:lookup ProductCategories
This creates a class in app/Lookups/:
namespace App\Lookups;
use Illuminate\Database\Eloquent\Model;
use Wezlo\FilamentLookups\Lookup;
class Countries extends Lookup
{
public function name(): string
{
return 'Countries';
}
public function description(): ?string
{
return 'List of supported countries';
}
public function isHierarchical(): bool
{
return false;
}
public function canAdd(): bool
{
return true;
}
public function canEdit(?Model $record = null): bool
{
return true;
}
public function canDelete(?Model $record = null): bool
{
return false; // protect country values from deletion
}
}
#2. Sync to database
php artisan lookups:sync
This command will:
- Create types for new Lookup classes
- Update existing types with any class changes
- Deactivate types whose class was removed
Run this during deployment or in your CI pipeline.
#3. Manage values in the panel
The plugin registers a Lookups page with a sidebar listing all synced types. Click a type to view and manage its values. The create/edit/delete actions respect the permissions defined in your Lookup class.
#Available Lookup Methods
| Method | Default | Description |
|---|---|---|
name() |
Class name as headline | Display name |
slug() |
Slugified name | URL-safe identifier |
description() |
null |
Optional description shown as subheading |
isHierarchical() |
false |
Enable parent-child values |
tenancyMode() |
'shared' |
'shared', 'tenant', or 'both' |
sortOrder() |
0 |
Navigation sort order |
canAdd() |
true |
Show/hide create button |
canEdit(?Model $record = null) |
true |
Show/hide edit action per record |
canDelete(?Model $record = null) |
true |
Show/hide delete action per record |
canView(?Model $record = null) |
true |
Show/hide lookup type visibility |
canReorder() |
true |
Enable drag-to-reorder |
#Per-Record Permissions
The canEdit(), canDelete(), and canView() methods receive the current record, allowing conditional logic per row:
use Illuminate\Database\Eloquent\Model;
use Wezlo\FilamentLookups\Lookup;
class OrderStatus extends Lookup
{
public function canEdit(?Model $record = null): bool
{
// prevent editing system-defined statuses
return ! $record?->metadata['is_system'];
}
public function canDelete(?Model $record = null): bool
{
// only allow deleting statuses that are not in use
return $record?->orders()->doesntExist() ?? true;
}
}
When called without a record (e.g. for navigation visibility), $record is null — the default true applies.
#Using LookupSelect in Forms
use Wezlo\FilamentLookups\Forms\Components\LookupSelect;
LookupSelect::make('country_id')
->lookupType('countries')
#Hierarchical display
LookupSelect::make('category_id')
->lookupType('product-categories')
->hierarchical()
#Dependent / cascading selects
LookupSelect::make('region_id')
->lookupType('regions')
->live(),
LookupSelect::make('city_id')
->lookupType('regions')
->dependsOn('region_id'),
#Using LookupService Programmatically
use Wezlo\FilamentLookups\Services\LookupService;
$service = app(LookupService::class);
$values = $service->getValuesForType('countries');
$roots = $service->getRootValues('product-categories');
$children = $service->getChildValues($parentId);
$options = $service->getOptionsForSelect('countries');
#Multi-Tenancy
Enable tenancy in config:
'tenancy' => [
'enabled' => true,
'tenant_model' => \App\Models\Company::class,
'tenant_id_column' => 'tenant_id',
],
Set the tenancy mode per Lookup class:
public function tenancyMode(): string
{
return 'both'; // 'shared', 'tenant', or 'both'
}
| Mode | Behavior |
|---|---|
| shared | Visible to all tenants |
| tenant | Only visible to the owning tenant |
| both | System defaults + tenant-specific values merged |
#HasLookups Trait
use Wezlo\FilamentLookups\Concerns\HasLookups;
class Company extends Model
{
use HasLookups;
}
$company->getLookupValues('countries');
#Configuration
php artisan vendor:publish --tag="filament-lookups-config"
| Option | Description | Default |
|---|---|---|
lookups_path |
Directory containing Lookup classes | app_path('Lookups') |
lookups_namespace |
PSR-4 namespace for Lookup classes | App\Lookups |
tables.lookup_types |
Types table name | lookup_types |
tables.lookup_values |
Values table name | lookup_values |
tenancy.enabled |
Enable multi-tenancy | false |
tenancy.tenant_model |
Tenant model class | null |
tenancy.tenant_id_column |
Tenant foreign key | tenant_id |
navigation_group |
Panel navigation group | Settings |
register_resource |
Register the Filament page | true |
#Plugin Configuration
FilamentLookupsPlugin::make()
->navigationGroup('Admin')
->navigationIcon('heroicon-o-rectangle-stack')
->navigationSort(10)
->tenancy()
->tenantModel(\App\Models\Company::class)
#License
MIT
The author
From the same author
Modal Notifications
Render any Filament notification as a blocking modal by chaining one method: ->asModal(). Multiple modal notifications fired in the same request are queued one at a time — the user dismisses one and the next slides in, no stacking.
Author:
Mustafa Khaled
Workspace Tabs
Browser-like tabs for Filament panels. Open multiple pages in tabs without losing context, drag to reorder, pin frequently accessed pages, and right-click for quick actions.
Author:
Mustafa Khaled
Record Freezer
Freeze individual Eloquent records against modification — finalised contracts, audited financial periods, legal holds
Author:
Mustafa Khaled
Record Watcher
Subscribe to individual Eloquent records and receive in-panel Filament notifications whenever they change — with the actor (who) and a field-level diff (what). Watches can carry conditions ("only if status changes", "only if amount > 10K"), can be paused, and live on a personal **My Watches** page scoped to the authenticated user. Every fan-out is also persisted to a permanent event log, so users can review the full change history even after dismissing notifications.
Author:
Mustafa Khaled
Featured Plugins
A selection of plugins curated by the Filament team
Blueprint
Filament Blueprint is a premium Laravel Boost extension that helps AI agents produce accurate, detailed implementation plans and security reports for Filament apps.
Filament
Spotlight Pro
Browse your Filament Panel with ease. Filament Spotlight Pro adds a Spotlight like Command Palette to your Filament Panel.
Dennis Koch
Data Lens
Advanced Data Visualization for Laravel Filament - a premium reporting solution enabling custom column creation, sophisticated filtering, and enterprise-grade data insights within admin panels.
Padmission