Lookups plugin screenshot
Dark mode ready
Multilingual support
Supports v5.x

Lookups

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.

Tags: Panels Kit Developer Tool
Supported versions:
5.x 4.x
Mustafa Khaled avatar Author: Mustafa Khaled

Documentation

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

Mustafa Khaled avatar Author: Mustafa Khaled

15 Year Laravel Developer

Plugins
10

From the same author

Workspace Tabs plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
5 stars
Tag: Panels Tag: Kit More tags: +1
Dark mode ready Multilingual support
Free
Get it now
Search Spotlight plugin thumbnail

Search Spotlight

A full-screen Spotlight / command-palette search overlay for Filament panels. Opens on ⌘K (configurable), aggregates results from multiple categories (records, resources, pages, actions, plus recent/pinned from localStorage), and composes Filament's built-in `GlobalSearchProvider` — every resource that already implements `getGloballySearchableAttributes()` shows up automatically.

Mustafa Khaled avatar Author: Mustafa Khaled
1 star
Tag: Panels
Dark mode ready Multilingual support
Free
Get it now
Export Pro plugin thumbnail

Export Pro

A comprehensive, model-agnostic export engine for Filament. Handles large datasets with background processing and real-time progress tracking, maintains full export history with audit trails, supports scheduled/recurring exports with delivery, and gives admins visibility into who exported what and when.

Mustafa Khaled avatar Author: Mustafa Khaled
0 stars
Tag: Action Tag: Developer Tool More tags: +3
Dark mode ready Multilingual support
$99.00
Buy now
Record Freezer plugin thumbnail

Record Freezer

Freeze individual Eloquent records against modification — finalised contracts, audited financial periods, legal holds

Mustafa Khaled avatar Author: Mustafa Khaled
2 stars
Tag: Panels Tag: Developer Tool More tags: +1
No dark mode support No multilingual support
Free
Get it now