Attaching records using the Repeater field and HasMany
Let's say you want to associate Players to Teams in your application. After reading the Laravel Documentation, you create this database table structure:
teams id - integer name - string players id - integer name - string team_player player_id - integer team_id - integer
You create the corresponding Player
model with a BelongsToMany
relationship to the Team
model
class Player extends Model{ protected $fillable = ['name']; public function teams() { return $this->belongsToMany(Team::class, 'team_player'); }} class Team extends Model{ protected $fillable = ['name']; public function players() { return $this->belongsToMany(Player::class, 'team_player'); }}
You then attach Players to a Team by calling $team->attach([$player->id])
, all is good!
Now in Filament, in your TeamResource
, you add a Repeater field to let your site administrators attach Players to Teams:
public static function form(Form $form): Form{ return $form ->schema([ TextInput::make('name'), Repeater::make('players') ->relationship() ->schema([ Select::make('player_id') ->label('Player') ->options(Player::pluck('name', 'id')), ]), ]);}
When you try to add a Player to a Team using the Repeater field and save, you see this error:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: players.name INSERT INTO "players" ("updated_at", "created_at") VALUES (2023-07-17 13:55:12, 2023-07-17 13:55:12)
What's happening? Filament is trying to create a new Player record instead of simply attaching the selected Player to the Team.
TeamPlayer
model:class TeamPlayer extends Model{ protected $table = 'team_player'; protected $fillable = ['team_id', 'player_id'];}
team_player
table schema:Schema::create('team_player', function (Blueprint $table) { $table->id(); $table->integer('team_id'); $table->integer('player_id'); $table->timestamps();});
HasMany
instead of BelongsToMany
:class Team extends Model{ protected $fillable = ['name']; public function teamPlayers() { return $this->hasMany(TeamPlayer::class, 'team_id', 'id'); }}
Repeater::make('teamPlayers') ->relationship() ->schema([ Select::make('player_id') ->label('Player') ->options(Player::pluck('name', 'id')), ]),
The Repeater should now correctly attach Players to Teams as intended:
No comments yet…