Saving a page with a category failed with "El campo categoría no está
en la lista de valores permitidos" — for every category, not only the
one being tried. Filament builds such a list through a query, which
handles `->relationship('category', 'name->es')`, but validates a choice
by reading the title back off the record as a property,
`$record->{'name->es'}`, which does not exist. No label, so every
option was refused.
The same pattern was in seven more places: a call's, a testimonial's,
a talk's and a repository's project, a testimonial's service, and the
page and application filters. TranslatedOptionLabel gives Filament the
record's own translation instead, in the language of whoever uses the
panel; the JSON path stays for search and ordering.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
30 lines
996 B
PHP
30 lines
996 B
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\Support;
|
|
|
|
use Closure;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* The label of a relationship option whose title is translatable.
|
|
*
|
|
* `->relationship('category', 'name->es')` builds the list fine — that path
|
|
* goes through a query — but to validate a choice Filament reads the title
|
|
* back off the record as a property, `$record->{'name->es'}`, which does not
|
|
* exist. Every choice then came back without a label and was refused as "not
|
|
* in the list of allowed values", whichever one it was. Given this, Filament
|
|
* asks the record instead, in the language of whoever is using the panel.
|
|
*
|
|
* The JSON path stays in `relationship()`: it is still what the search box
|
|
* queries and the list is ordered by.
|
|
*/
|
|
final class TranslatedOptionLabel
|
|
{
|
|
public static function using(string $attribute): Closure
|
|
{
|
|
return fn (Model $record): ?string => $record->getTranslation($attribute, app()->getLocale());
|
|
}
|
|
}
|