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

Lookups

Community

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

Package health

Beta

Automated checks of this plugin's Composer package

92 / 100
Security 85
Maintenance 100
Ecosystem 100
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.lock is 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.2 supports current PHP 8.5.
  • Skipped: Current Symfony version supported
Third-party plugin. This is built by the community, not the Filament team. Filament does not review, endorse, or vet the security of plugins outside the 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 .
Powered by Plumb Last scanned 3 weeks ago

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
11
Stars
47

From the same author

Modal Notifications plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
92 / 100 package health score out of 100
4 stars
Tag: Developer Tool Tag: Panels
Dark mode ready Multilingual support
Free
Get it now
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
82 / 100 package health score out of 100
6 stars
Tag: Panels Tag: Kit More tags: +1
Dark mode ready Multilingual support
Free
Get it 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
92 / 100 package health score out of 100
4 stars
Tag: Panels Tag: Developer Tool More tags: +1
No dark mode support No multilingual support
Free
Get it now
Record Watcher plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
92 / 100 package health score out of 100
4 stars
Tag: Action Tag: Developer Tool More tags: +2
Dark mode ready Multilingual support
Free
Get it now