Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

raobilal4822's avatar

Filament Multi-Tenancy: Building a Global Company Filter for Super Admins in header

Hello, I am working on a multi-tenant application using Laravel and Filament v3. I need help implementing a "Company Switcher" feature for the super admin.

Here is my current setup:

Multi-tenancy: I have a single database. Most of my models (like Product, Invoice, etc.) have a company_id column to associate them with a company.

Super Admin: My users table has a boolean field is_super_admin. If this is true, the user is a super admin.

Authorization:

The super admin can access all data from all companies. I've set this up in my AuthServiceProvider using Gate::before:

Gate::before(function ($user, $ability) { return $user->is_super_admin ? true : null; });

Regular users can only see data belonging to their own company. I am enforcing this using a global scope called CompanyScope:

// app/Scopes/CompanyScope.php class CompanyScope implements Scope { public function apply(Builder $builder, Model $model): void { if (auth()->check() && ! auth()->user()->is_super_admin) { $builder->where($model->qualifyColumn('company_id'), auth()->user()->company_id); } } }

// This scope is applied in my models like this: // protected static function boot() // { // parent::boot(); // static::addGlobalScope(new CompanyScope); // }

My Goal:

I want to add a dropdown menu to the top navigation bar in the Filament admin panel. This dropdown should have the following features:

It should only be visible to the super admin.

It should list all companies from my companies table.

The first option in the dropdown should be "All Companies".

When the super admin selects a specific company from the dropdown, the entire admin panel should refresh and filter all data to show only the records for that selected company.

The selected company's ID should be stored in the user's session so that the filter remains active as the admin navigates between different pages.

When the super admin selects "All Companies," the filter should be cleared, and they should see all data again (restoring the default behavior).

My Question:

What is the best way to implement this company switcher dropdown in Filament? I need a complete solution that explains:

How to render a custom dropdown in the top navigation bar (perhaps using a RenderHook).

How to populate this dropdown with a list of all companies and an "All Companies" option.

How to create a Livewire component or method that handles the selection, saves the selected company ID to the session, and reloads the page.

How to modify my CompanyScope to check for this session variable. The scope should apply the where('company_id', ...) filter for the super admin only if a company ID is present in the session.

Please provide a complete code example, including the necessary Blade view, Livewire component/method, and the updated CompanyScope class.

0 likes
2 replies
LaryAI's avatar
Level 58

Absolutely! Here’s a step-by-step solution for implementing a Company Switcher for super admins in Filament v3, including all the code you need.


1. Livewire Component: CompanySwitcher

Create a Livewire component to handle the dropdown and session logic.

Generate the component:

php artisan make:livewire CompanySwitcher

app/Http/Livewire/CompanySwitcher.php


2. Blade View for the Component

resources/views/livewire/company-switcher.blade.php

<div>
    <form wire:submit.prevent>
        <select wire:model="selectedCompany" wire:change="updatedSelectedCompany($event.target.value)" class="filament-dropdown">
            <option value="all">All Companies</option>
            @foreach($companies as $company)
                <option value="{{ $company->id }}">{{ $company->name }}</option>
            @endforeach
        </select>
    </form>
</div>

Style the select as you wish, or use Filament's classes.


3. Add the Switcher to Filament’s Topbar

Use Filament’s Render Hook to inject the component into the navigation bar.

In your Filament Panel Provider (e.g., app/Providers/Filament/AdminPanelProvider.php):

use Filament\Panel;
use Filament\Navigation\NavigationBuilder;

public function panel(Panel $panel): Panel
{
    return $panel
        // ... other config
        ->renderHook(
            'panels::topbar.start',
            fn () => auth()->user()?->is_super_admin
                ? view('filament.components.company-switcher')
                : ''
        );
}

Create the Blade file to render the Livewire component:

resources/views/filament/components/company-switcher.blade.php

@livewire('company-switcher')

4. Update the CompanyScope

app/Scopes/CompanyScope.php


5. Apply the Scope to Your Models

In each model (e.g., Product, Invoice, etc.):

protected static function booted()
{
    static::addGlobalScope(new \App\Scopes\CompanyScope);
}

6. (Optional) Clear Session on Logout

To avoid session leaks, clear the filter on logout. In your Logout logic:

session()->forget('filament_company_id');

Summary

  • Livewire component handles the dropdown and session.
  • Render hook injects the switcher for super admins.
  • CompanyScope checks the session for the filter.
  • Dropdown lists all companies and "All Companies".
  • Session persists the filter across navigation.

This approach is clean, leverages Filament’s extensibility, and keeps your authorization logic centralized.

Let me know if you need further clarification!

jdc1898's avatar

Why not use the built in multi-tenant feature in filament? It does what your looking for out of the box.

1 like

Please or to participate in this conversation.