How to use pivotData with enum column in a Filament 3 many-to-many relationship?

Updated: Feb 14, 2025

How to use pivotData with enum column in a Filament 3 many-to-many relationship?

To use pivotData with an enum column in a Filament 3 many-to-many relationship, you'll need to follow these steps:

  1. Define your models: First, define your models with the many-to-many relationship and the enum column. Here's an example using Post and Tag models:
use Filament\Models\Contracts\HasTable;
use Filament\Models\Contracts\HasRelations;
use Filament\Models\Model;
use Spatie\Tags\HasTags;
use Spatie\Tags\Tag;

class Post extends Model implements HasTable, HasRelations
{
    use HasTags;

    protected $table = 'posts';

    protected $fillable = ['title', 'content'];

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }
}

class Tag extends Model implements HasTable, HasRelations
{
    protected $table = 'tags';

    protected $fillable = ['name'];
}
  1. Define your pivot table: Create a pivot table to store the many-to-many relationship data. In this example, we'll add an enum column named status:
use Filament\Models\Contracts\HasTable;
use Filament\Models\Model;

class PostTag extends Model implements HasTable
{
    protected $table = 'post_tags';

    protected $fillable = ['post_id', 'tag_id', 'status'];

    public function post()
    {
        return $this->belongsTo(Post::class);
    }

    public function tag()
    {
        return $this->belongsTo(Tag::class);
    }
}
  1. Use pivotData: Now, you can use pivotData to access the data from the pivot table. Here's an example of how to use it in a Filament resource:
use Filament\Facades\Filament;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables\Columns\TextColumn;
use Spatie\Tags\Tag;

class PostResource extends Resource
{
    protected static string $model = Post::class;

    public function form(Form $form): Form
    {
        // ...
    }

    public function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('title')->label('Title'),
                TextColumn::make('content')->label('Content'),
                TextColumn::make('tags.name')->label('Tags')->searchable()->sortable(),
                TextColumn::make('status')->label('Status'),
            ])
            ->filters([
                // ...
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
                Tables\Actions\DeleteAction::make(),
            ])
            ->extensions([
                Tables\Extensions\RelationshipLabels::make(),
                Tables\Extensions\Actions\CreateAction::make(),
            ])
            ->headerActions([
                Tables\Actions\CreateAction::make(),
            ])
            ->query(fn ($query) => $this->model()->with('tags.pivot'));
    }

    protected function model(): \Illuminate\Database\Eloquent\Builder
    {
        return Post::query()->with('tags.pivot');
    }
}

In the table method, we're using with('tags.pivot') to eager load the pivot data. Then, we're using TextColumn::make('tags.name') to display the tag name, and TextColumn::make('status') to display the status from the pivot table.

  1. Display the enum value: To display the enum value as a human-readable string, you can use the asText method provided by Filament:
TextColumn::make('status')->label('Status')->asText()

This will automatically convert the enum value to its corresponding label based on the status column in the PostTag model.

Now, you should be able to use pivotData with an enum column in a Filament 3 many-to-many relationship.