Pola administracyjne Filament
Bezpłatny pakiet rankbeam/laravel-seo-filament dodaje kompletną sekcję SEO do formularza dowolnego zasobu Filament — dwie linie na zasób. Obsługuje Filament 4.x i 5.x (Livewire 3 i 4). Edycja metadanych jest bezpłatna; Pro dodaje skany i ocenę widoczną w poniższym przykładzie.
Wymagania wstępne
Użyj istniejącego panelu Filament 4 lub 5 i modelu z traitem HasSEO rdzenia. Przed dodaniem edytora wykonaj Szybki start rdzenia, łącznie z migracjami i renderowaniem.
Instalacja
composer require rankbeam/laravel-seo-filamentModel zasobu musi używać traitu HasSEO rdzenia.
Dodaj sekcję do zasobu
use Rankbeam\Seo\Filament\Concerns\HasSEOFields;
class PostResource extends Resource
{
use HasSEOFields; // 1
public static function form(Schema $schema): Schema
{
return $schema->components([
TextInput::make('title'),
// ...
static::seoSection(), // 2
]);
}
}Sprawdź zapisany wynik
Otwórz istniejący rekord. Wpisz opis SEO, zapisz i ponownie załaduj formularz. Wartość powinna zostać zachowana, podgląd powinien ją pokazywać, a źródło powinno wskazywać Ręcznie. Sprawdź sekcję <head> wyrenderowanej strony, aby potwierdzić, że ten sam opis trafia do odwiedzających.

Przykład z demo Merchant. Pola korzystają z motywu Twojego panelu; dostępne kontrolki i limity znaków zależą od zainstalowanej wersji i konfiguracji.
Sekcja zawiera:
- Tytuł i opis z licznikami znaków na żywo — limit wynika z zasad długości rdzenia dla wpisywanego systemu pisma (60/160 dla tekstu łacińskiego, około 30/80 dla CJK, liczone jako grafemy).
- Główne słowa kluczowe — pole tagów. Wpisujesz zwykłe słowa kluczowe; są zapisywane w strukturze
[{keyword, is_primary}]rdzenia (pierwsze jest główne), dzięki czemugetPrimaryKeyword()iSEODataodczytują je bez zmian. Włączseo.keywords.enabled, aby polecenieseo:auditi skan Pro oznaczały strony nadal pozbawione słowa kluczowego (domyślnie wyłączone — jeden wspólny przełącznik, zobacz Konfiguracja). - Kanoniczny URL (pusty = automatyczny, bez parametrów zapytania).
- Lista wyboru Robots (pusta = domyślna wartość witryny).
- Przesyłanie obrazu do udostępniania w mediach społecznościowych (og:image / twitter:image), zapisywanego na domyślnym dysku Filament w
seo/. - Podgląd wyniku wyszukiwania, który odzwierciedla łańcuch wartości zastępczych resolvera na żywo podczas pisania.
- Wskaźniki źródeł — warstwa resolvera, która dostarczyła wynikową wartość każdego pola: Ręcznie, Z treści, Domyślne dla typu modelu, Domyślne globalne, Konfiguracja witryny lub Wyprowadzone z URL.
Ograniczanie pól
static::seoSection(['title', 'description'])Akceptuje dowolny podzbiór title, description, focus_keywords, canonical, robots, og_image.
Bez traitu SEOFields::make(?array $only) zwraca bezpośrednio tę samą sekcję.
Jak zapisywane są wartości
Sekcja jest powiązana z grupą stanu seo_meta i zapisuje przez relację seoMeta() rdzenia (aktualizacja lub utworzenie) — bez kolumn we własnych tabelach. Wartości natychmiast stają się warstwą 6 (jawną) w resolverze.
Kilka języków
Rdzeń przechowuje jeden rekord seo_meta na parę (model, ustawienia regionalne). Przekaż języki, w których strona jest opublikowana, a sekcja wyświetli jedną kartę na język (Filament 1.9):
static::seoSection(locales: ['en', 'it', 'ja']);
// or, without the trait
SEOFields::make(locales: ['en', 'it', 'ja']);Możesz też ustawić to raz dla wszystkich zasobów w konfiguracji pakietu:
php artisan vendor:publish --tag=seo-filament-config// config/seo-filament.php
'locales' => ['en', 'it', 'ja'],Każda karta edytuje własny rekord i ma własne:
- liczniki — zgodne z zasadami długości dla systemu pisma danego języka, więc pusty japoński tytuł pokazuje
0 / 30, a angielska karta tej samej strony —0 / 60; - podgląd (SERP / karta społecznościowa) renderowany z rozstrzygniętych wartości danego wariantu językowego;
- wskaźniki wartości zastępczych opisujące rekord danego wariantu językowego;
- oznaczenie liczby ustawionych pól w danej wersji, dzięki któremu puste tłumaczenia są łatwo widoczne.
Karta jest podpisana nazwą języka w języku panelu (Italiano / Italian), gdy załadowano ext-intl, a w przeciwnym razie — kodem. Wszystkie karty są walidowane i zapisywane razem; język, dla którego niczego nie wpisano, nigdy nie otrzymuje pustego rekordu zastępczego.
Własne powiązania stanu formularza
Przy kilku wariantach językowych ścieżka stanu to seo_meta.{locale}.title; przy jednym pozostaje seo_meta.title. We własnych akcjach formularza używaj odpowiedniej ścieżki.

Demo Merchant, 9 września 2026, z locales: ['en', 'it', 'ja']. Pusta karta japońska ma własne liczniki. Angielski tytuł pochodzi tutaj z wartości zastępczej treści modelu demonstracyjnego: dodanie karty języka nie tłumaczy treści. Ocena Pro nad polami jest wynikiem ostatniego skanu rekordu, a nie osobną oceną każdej karty języka.
Z wtyczką tłumaczeń
Z lara-zeus/spatie-translatable 1.x na Filament 4 lub 2.x na Filament 5 używaj adapterów stron Edit i Create dostarczanych przez Rankbeam. Zastąp tylko importy traitów stron; zachowaj traity zasobu/listy wtyczki, wtyczkę panelu i akcję LocaleSwitcher:
// In your EditPost page:
use Rankbeam\Seo\Filament\Resources\Pages\EditRecord\Concerns\Translatable;
// In your CreatePost page (a separate file):
use Rankbeam\Seo\Filament\Resources\Pages\CreateRecord\Concerns\Translatable;Każda strona nadal deklaruje use Translatable; wewnątrz swojej klasy. Wtyczka pozostaje opcjonalną zależnością aplikacji. Używaj najnowszej wersji z poprawkami; lokalny scenariusz integracyjny obejmuje wtyczkę 1.0.4 / Filament 4.13.1 oraz wtyczkę 2.0.1 / Filament 5.8.1.
Przełączanie zachowuje w edytorze niezapisaną treść nadrzędnego rekordu, metadane SEO i wersje robocze danych strukturalnych. Zapis waliduje każdy odwiedzony język i zapisuje je razem w transakcji bazy danych. Błąd walidacji otwiera język wymagający uwagi. Przesyłane pliki są zapisywane przy zapisie formularza; opuszczenie lub ponowne załadowanie strony odrzuca niezapisane wersje robocze. Zapis wersji roboczej nie tłumaczy brakujących treści za Ciebie.
Adaptery zachowują zwykłe hooki przed/po i mutatory danych formularza. Jeśli Twoja strona nadpisuje handleRecordCreation(), handleRecordUpdate(), callHook() lub metody transakcji, włącz zachowanie adaptera do tych zmian i przetestuj zapis. Transakcje bazy danych nie wycofują zapisów w systemie plików; aplikacje powinny zachować zwykłe czyszczenie osieroconych plików.
Dla własnych pól tekstowych aktualizowanych na żywo w Livewire 3 wybieraj ->live() lub ->live(onBlur: true) zamiast jawnego debounce: ten ostatni opóźnia lokalny stan modelu i może zgubić ostatnie naciśnięcia klawiszy podczas szybkiej zmiany języka. Pola tytułu i opisu Rankbeam używają domyślnego debounce żądań.
Same traity stron z wtyczki ponownie wypełniają formularze podczas przełączania. Rankbeam chroni przed ich przypadkowymi zapisami metadanych, ale te traity nie zachowują wersji roboczych SEO; przenieś strony Edit/Create na adaptery. Jawne karty locales: pozostają wspólnym edytorem i mają pierwszeństwo przed przełącznikiem strony.
Bez jawnej listy języków ani ustawień regionalnych strony sekcja edytuje wariant zgodny z ustawieniami aplikacji.
Dane strukturalne (schema.org)
Opcjonalna sekcja Dane strukturalne pozwala redaktorom dołączać dane JSON-LD dla wyników rozszerzonych bez dotykania kodu. Dodaj ją obok sekcji SEO:
public static function form(Schema $schema): Schema
{
return $schema->components([
// ... your fields ...
static::seoSection(),
static::seoSchemaSection(), // optional
]);
}(lub bezpośrednio SEOSchemaFields::make(), bez traitu).
Zapisuje w kolumnie seo_meta.schema_jsonld rdzenia — tę samą wartość generuje renderer danych strukturalnych — i jest wyłącznie powiązaniem interfejsu: każdy dokument powstaje przez builder danych strukturalnych rdzenia i przed zapisem jest walidowany przez SchemaValidator rdzenia. Sekcja nie dodaje własnej logiki danych strukturalnych.
Sekcja oferuje:
- Automatyczna ścieżka nawigacyjna — pojedynczy przełącznik, pokazany na początku jako korzyść niewymagająca konfiguracji. Wyprowadza
BreadcrumbListz łańcucha rodziców rekordu przezBreadcrumbSchema::fromModelAncestors(). Niczego nie trzeba uzupełniać — podąża za przodkami modelu. - Bloki schematu — pole powtarzalne. Każdy blok to FAQ (pary pytanie / odpowiedź →
FAQPage) albo Produkt (nazwa, opis, obraz, marka, SKU, cena i waluta, dostępność →Product), budowany przez builderyFAQSchema/ProductSchemardzenia.
Walidacja
Blok tworzący nieprawidłowy JSON-LD jest odrzucany przy zapisie z komunikatem walidatora rdzenia — np. wpis FAQ bez odpowiedzi lub Product bez obrazu albo oferty (ten builder wymaga tych pól; nie jest to pełny opis wymagań Google dla każdej funkcji wyszukiwania Product). Puste bloki są po prostu ignorowane.
Co zapisuje
schema_jsonld zawiera zbudowane dokumenty: pojedynczy obiekt, gdy jest jeden, albo tablicę JSON, gdy jest ich kilka (najpierw ścieżka nawigacji, potem Twoje bloki). Obie formy są poprawnym JSON-LD i są renderowane bez zmian przez @seo / renderSchema().
Dane strukturalne, którymi nie zarządza
Dane strukturalne napisane w kodzie, których ten edytor nie potrafi przedstawić — ręcznie przygotowany @graph, nietypowy @type lub Product z polami niedostępnymi w formularzu (recenzje, oceny, GTIN/MPN) — są zachowywane dosłownie. Otwarcie i zapis formularza nigdy ich nie nadpisują.
Rozwiązywanie problemów
- Zapisanego pola brakuje na stronie: potwierdź, że szablon renderuje
@seo($model)dla tego samego rekordu i wariantu językowego. - Pole nadal korzysta z wartości zastępczej: sprawdź, czy ma zapisane nadpisanie w aktywnym języku. Wskaźniki źródeł wskazują rozstrzygniętą warstwę.
- Brakuje karty języka: sprawdź jawny argument
locales:, konfigurację pakietu i ewentualny przełącznik tłumaczeń na poziomie strony. Ich pierwszeństwo opisano powyżej.
Testowanie własnego panelu w Testbench
Jeśli uruchamiasz Filament wewnątrz orchestra/testbench, zarejestruj SupportServiceProvider Filament przed LivewireServiceProvider — Filament ponownie wiąże DataStore Livewire, a błędna kolejność powoduje niepowodzenie każdego testu Livewire z ViewErrorBag::put(): ... null given. Nie dotyczy to zwykłych aplikacji (wykrywanie pakietów poprawnie porządkuje dostawców).