Filament uses a "tenant-aware" approach to make sure each tenant (in your case, an organization) only sees and manages their own records. To achieve this, Filament expects two relationships to be defined:
An "ownership" relationship on the resource model (e.g., users on Organization). This tells Filament who owns this record. A relationship on the tenant model (e.g., organizations on User). This links the tenant to the resource. For Filament to work smoothly, these relationships must exist and must be set up correctly in both directions.
Steps to Fix Your Problem
Check the Ownership Relationship on the Organization Model In your Organization model, you already have this relationship:
public function users(): BelongsToMany { return $this->belongsToMany(User::class); }
This is correct, and Filament should use it as the "ownership" relationship.
Check the Tenant Relationship on the User Model Your User model should define a corresponding relationship back to the Organization. For example:
public function organizations(): BelongsToMany { return $this->belongsToMany(Organization::class); }
This relationship allows Filament to understand which organizations a user belongs to.
Add Scoping Logic to getEloquentQuery You need to explicitly scope the OrganizationResource to show only the records related to the current tenant. Here's how to do it:
public static function getEloquentQuery(): Builder { // If the user belongs to an admin organization, show all organizations $isAdmin = auth()->user()?->organizations()->where('is_admin', true)->exists();
if ($isAdmin) {
return parent::getEloquentQuery();
}
// Otherwise, scope to organizations the user is part of
return parent::getEloquentQuery()
->whereHas('users', function ($query) {
$query->where('users.id', auth()->id());
});
}
This ensures that regular users only see the organizations they belong to, while admins see everything.
Example:
Add an organization_id column to models like Media or Game. Define relationships back to Organization:
public function organization(): BelongsTo
{
return $this->belongsTo(Organization::class);
}
Then, scope their queries accordingly, similar to what we did in OrganizationResource.
Set the Tenant in the Panel Your AdminPanelProvider is almost correct. Ensure you’ve defined the tenant method to use the Organization model. This helps Filament apply the tenant scope consistently:
->tenant(Organization::class, slugAttribute: 'slug')
This line ensures Filament knows how to resolve the active tenant.
Test as a regular user: Log in as a user belonging to a single organization. Check if only their organization is visible. Test as an admin user: Log in as a user with access to the admin organization. Check if they see all organizations.
Why Your Current Setup Isn’t Working? -The missing piece is that Filament doesn’t know how to scope data because:
1.The relationships between User and Organization are not clearly defined for Filament. 2.Tenant scoping isn’t explicitly applied in getEloquentQuery.
Once these are corrected, Filament will automatically filter data based on the current tenant.
Every tenant-aware model must:
1.Have a tenant field (organization_id, team_id, etc.). 2.Define relationships that link the tenant and resource model. 3.Use getEloquentQuery to scope data when necessary.
I hope this clarifies everything! Let me know if you need more guidance. 😊