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

myregistration's avatar

Save model's relationship value to Table SelectColumn

If I use a Filament Table SelectColumn I can't use a field that is a relationship of the Setting model record like make('preferences.value) because I get an

"Array to string"

error if I assign the relative field name with dot syntax, but if I leave the field make('') name an empty string and save the value in beforeStateUpdated() method I get error message

"Too few arguments to function Illuminate\Database\Eloquent\Model::setAttribute(), 1 passed in /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php on line 1093 and exactly 2 expected"

I assume because it has no name. Since I can save the value in beforeStateUpdated() is there way to prevent the state from updating? I know, it's kludgy. Any suggestions how to resolve this or better way to do it?

0 likes
3 replies
LaryAI's avatar
Level 58

To address the issue of saving a model's relationship value using a Filament Table SelectColumn, you can follow a more structured approach. The main problem arises from trying to directly access a relationship attribute using dot notation, which isn't directly supported in this context.

Here's a step-by-step solution to handle this:

  1. Define an Accessor in the Model: Create an accessor in your Setting model to get the related value. This way, you can access the relationship value as a simple attribute.

    // In your Setting model
    public function getPreferencesValueAttribute()
    {
        return $this->preferences->value;
    }
    
  2. Use the Accessor in the SelectColumn: Use the accessor in your Filament Table SelectColumn definition.

    use Filament\Tables\Columns\SelectColumn;
    
    SelectColumn::make('preferences_value')
        ->label('Preferences Value')
        ->options([
            'option1' => 'Option 1',
            'option2' => 'Option 2',
            // Add your options here
        ])
        ->afterStateUpdated(function ($state, $record) {
            // Update the related model's value
            $record->preferences->value = $state;
            $record->preferences->save();
        }),
    
  3. Prevent State from Updating Directly: Since you want to handle the update manually, you can use the afterStateUpdated method to save the value to the related model and prevent the state from updating directly.

Here is the complete code example:

use Filament\Tables\Columns\SelectColumn;

// In your Setting model
public function getPreferencesValueAttribute()
{
    return $this->preferences->value;
}

// In your Filament Table definition
SelectColumn::make('preferences_value')
    ->label('Preferences Value')
    ->options([
        'option1' => 'Option 1',
        'option2' => 'Option 2',
        // Add your options here
    ])
    ->afterStateUpdated(function ($state, $record) {
        // Update the related model's value
        $record->preferences->value = $state;
        $record->preferences->save();
    }),

This approach ensures that you can display and update the related model's value without running into the "Array to string" or "Too few arguments" errors. The accessor provides a clean way to access the relationship value, and the afterStateUpdated method allows you to handle the update logic manually.

myregistration's avatar

@LaryAI I don't think this would work because the relationship for Setting's preferences is HasMany so I get error

"Property [value] does not exist on this collection instance."

myregistration's avatar

I got the SelectColumn to work with the relative record, but I had to use getStateUsing() to set the initial option and updateStateUsing() to save the selected one.

               Tables\Columns\SelectColumn::make('')
                    ->label('Preference')
                    ->getStateUsing(function ($record, Component $livewire) {

                        $state = $record->organizationPreferences()
                            ->where('organization_id', $livewire->organization->id)
                            ->first()
                            ->value;

                        return $state;
                    })
                    ->updateStateUsing(function ($record, $state, Component $livewire) {

                        $preference = OrganizationPreference::updateOrCreate(
                            ['organization_id' => $livewire->organization->id, 'setting_id' => $record->id],
                            ['value' => $state]
                        );

                        return $state;
                    })
                    ->options(fn ($record) => array_combine($record->options, $record->options))
                    ->default(fn ($record) =>  $record->default),

Please or to participate in this conversation.