Перейти к содержимому

Поля панели Filament

Бесплатный пакет rankbeam/laravel-seo-filament добавляет полноценный SEO-раздел в форму любого ресурса Filament — две строки на ресурс. Поддерживаются Filament 4.x и 5.x (Livewire 3 и 4). Редактирование метаданных бесплатно; Pro добавляет сканирование и оценку, показанную в примере ниже.

Предварительные требования

Используйте существующую панель Filament 4 или 5 и модель с трейтом HasSEO ядра. Перед добавлением редактора пройдите быстрый старт ядра, включая миграции и вывод.

Установка

bash
composer require rankbeam/laravel-seo-filament

Модель ресурса должна использовать трейт HasSEO ядра.

Добавление раздела в ресурс

php
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
        ]);
    }
}

Проверка сохранённого результата

Откройте существующую запись. Введите SEO-описание, сохраните и перезагрузите форму. Значение должно сохраниться и появиться в предпросмотре, а источник должен показывать Вручную. Проверьте <head> отрендеренной страницы, чтобы убедиться, что посетители получают то же описание.

SEO-поля демо Merchant: заголовок, описание, канонический URL, изображение для соцсетей, предпросмотр поиска и источники итоговых значений.

Пример из демо Merchant. Поля используют тему вашей панели; доступные элементы управления и лимиты символов зависят от установленной версии и конфигурации.

Раздел включает:

  • Заголовок и описание с живыми счётчиками символов. Лимит задаёт политика длины ядра для вводимой письменности: 60/160 для латиницы, около 30/80 для CJK, с подсчётом графем.
  • Ключевые слова — поле тегов. Вы вводите обычные ключевые слова; они сохраняются в структурированном формате ядра [{keyword, is_primary}] (первое считается основным), поэтому getPrimaryKeyword() и SEOData читают их без изменений. Включите seo.keywords.enabled, чтобы команда seo:audit и сканирование Pro отмечали страницы без ключевого слова. По умолчанию выключено; используется один переключатель, см. Конфигурация.
  • Canonical-URL (пусто = автоматически, без строки запроса).
  • Список Директива robots (пусто = значение сайта по умолчанию).
  • Загрузку изображения для соцсетей (og:image / twitter:image), сохраняемого на диске Filament по умолчанию в seo/.
  • Предпросмотр результата поиска, который во время ввода отражает цепочку резервных значений резолвера.
  • Индикаторы источников: какой уровень резолвера дал фактическое значение каждого поля — Вручную, Из контента, Значение по умолчанию для типа модели, Глобальное значение по умолчанию, Конфигурация сайта или Получено из URL.

Ограничение набора полей

php
static::seoSection(['title', 'description'])

Принимается любое подмножество title, description, focus_keywords, canonical, robots, og_image.

Без трейта SEOFields::make(?array $only) возвращает тот же раздел напрямую.

Как сохраняются значения

Раздел привязывается к группе состояния seo_meta и сохраняется через связь seoMeta() ядра (обновление или создание). В ваших таблицах не появляются новые столбцы, а значения сразу становятся шестым, явным уровнем резолвера.

Несколько языков

Ядро хранит одну строку seo_meta на пару (модель, локаль). Передайте локали, на которых опубликована страница: раздел выведет вкладку для каждого языка (Filament 1.9):

php
static::seoSection(locales: ['en', 'it', 'ja']);
// or, without the trait
SEOFields::make(locales: ['en', 'it', 'ja']);

Или задайте их один раз для всех ресурсов в конфигурации пакета:

bash
php artisan vendor:publish --tag=seo-filament-config
php
// config/seo-filament.php
'locales' => ['en', 'it', 'ja'],

Каждая вкладка редактирует собственную строку и имеет свои:

  • счётчики по политике длины для письменности языка: пустой японский заголовок показывает 0 / 30, а английская вкладка той же страницы — 0 / 60;
  • предпросмотр поисковой выдачи и карточки соцсетей из итоговых значений этой локали;
  • индикаторы резервных значений, описывающие строку этой локали;
  • значок с количеством заполненных полей этой версии, чтобы пустые переводы были заметны.

При загруженном ext-intl вкладка подписывается названием языка на языке панели (Italiano / Italian), иначе — кодом. Все вкладки проходят валидацию и сохраняются вместе; для языка, в котором ничего не введено, строка-заглушка не создаётся.

Собственные привязки состояния формы

При нескольких локалях путь состояния — seo_meta.{locale}.title; при одной он остаётся seo_meta.title. Используйте соответствующий путь в собственных действиях формы.

Английская, итальянская и японская вкладки демо Merchant; лимиты японского заголовка и описания — 30 и 80, описание не задано.

Демо Merchant, 9 сентября 2026 года, с locales: ['en', 'it', 'ja']. Пустая японская вкладка использует собственные счётчики. Английский заголовок здесь взят из резервного контентного значения демо-модели: добавление языковой вкладки не переводит контент. Оценка Pro над полями — результат последнего сканирования записи, а не отдельная оценка каждой языковой вкладки.

С плагином переводов

При использовании lara-zeus/spatie-translatable 1.x на Filament 4 или 2.x на Filament 5 применяйте адаптеры страниц Rankbeam для Edit и Create. Замените только импорты трейтов страниц; оставьте трейты ресурсов и списков, плагин панели и действие LocaleSwitcher:

php
// 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;

Каждая страница по-прежнему объявляет use Translatable; внутри класса. Плагин остаётся необязательной зависимостью приложения. Используйте его последнюю исправленную версию; локальная интеграционная фикстура покрывает плагин 1.0.4 / Filament 4.13.1 и плагин 2.0.1 / Filament 5.8.1.

При переключении в редакторе сохраняются несохранённый контент основной записи, SEO-метаданные и черновики структурированных данных. Сохранение проверяет каждый посещённый язык и записывает их вместе в транзакции базы данных. При ошибке валидации открывается требующий внимания язык. Загрузки записываются при сохранении; выход со страницы или её перезагрузка удаляет несохранённые черновики. Сохранение черновика не переводит недостающий контент.

Адаптеры сохраняют обычные хуки до и после операций и преобразователи данных формы. Если страница переопределяет handleRecordCreation(), handleRecordUpdate(), callHook() или методы транзакций, включите поведение адаптера в эту доработку и проверьте сохранение. Транзакции базы данных не откатывают запись в файловую систему; приложение должно сохранять обычную очистку файлов без связанных записей.

Для собственных живых текстовых полей на Livewire 3 предпочитайте ->live() или ->live(onBlur: true) явно заданному debounce: последний задерживает локальное состояние модели и может потерять последние нажатия при быстром переключении локали. Поля заголовка и описания Rankbeam используют стандартную задержку запросов.

Исходные трейты страниц плагина при переключении заново заполняют формы. Rankbeam защищает от их случайных записей метаданных, но эти трейты не сохраняют SEO-черновики; переведите страницы Edit/Create на адаптеры. Явные вкладки locales: остаются общим редактором и имеют приоритет над переключателем страницы.

Без явного списка локалей или локали страницы раздел редактирует локаль приложения.

Структурированные данные (schema.org)

Необязательный раздел Структурированные данные позволяет редакторам добавлять JSON-LD-разметку для расширенных результатов без изменения кода. Добавьте его рядом с SEO-разделом:

php
public static function form(Schema $schema): Schema
{
    return $schema->components([
        // ... your fields ...
        static::seoSection(),
        static::seoSchemaSection(),     // optional
    ]);
}

(или используйте SEOSchemaFields::make() напрямую, без трейта).

Он записывает данные в столбец ядра seo_meta.schema_jsonld — то же значение, которое выводит рендерер разметки, — и является только привязкой интерфейса: каждый документ создаётся построителем разметки ядра и перед сохранением проверяется SchemaValidator ядра. Собственной логики разметки он не добавляет.

Раздел предлагает:

  • Автоматические хлебные крошки — один переключатель, представленный первым как возможность без настройки. Создаёт BreadcrumbList из цепочки родителей записи через BreadcrumbSchema::fromModelAncestors(). Заполнять ничего не нужно: используются предки модели.
  • Блоки схемы — повторитель. Каждый блок представляет FAQ (пары вопрос/ответ → FAQPage) или Товар (название, описание, изображение, бренд, SKU, цена и валюта, наличие → Product), создаваемые построителями ядра FAQSchema / ProductSchema.

Валидация

Блок, который сформировал бы некорректный JSON-LD, отклоняется при сохранении с сообщением валидатора ядра: например, FAQ без ответа или Product без изображения либо предложения. Эти поля требует данный построитель; это не полное описание требований Google для каждой поисковой функции Product. Пустые блоки просто игнорируются.

Что сохраняется

schema_jsonld содержит построенные документы: один объект, если документ один, или JSON-массив, если их несколько (сначала хлебные крошки, затем ваши блоки). Оба варианта — корректный JSON-LD, который без изменений выводится через @seo / renderSchema().

Разметка вне управления редактора

Разметка, написанная в коде и не представимая этим редактором, — собственный @graph, нестандартный @type или Product с полями, которых нет в форме (отзывы, рейтинги, GTIN/MPN), — сохраняется дословно. Открытие и сохранение формы её не затирают.

Устранение неполадок

  • Сохранённого поля нет на странице: убедитесь, что шаблон выводит @seo($model) для той же записи и локали.
  • Поле всё ещё использует резервное значение: проверьте, сохранено ли переопределение поля в активном языке. Индикаторы источников показывают итоговый уровень.
  • Языковая вкладка отсутствует: проверьте явный аргумент locales:, конфигурацию пакета и переключатель переводов страницы. Их приоритет описан выше.
Тестирование собственной панели в Testbench

Если вы загружаете Filament внутри orchestra/testbench, зарегистрируйте его SupportServiceProvider до LivewireServiceProvider. Filament заново привязывает DataStore Livewire, и неверный порядок ломает каждый тест Livewire с ошибкой ViewErrorBag::put(): ... null given. Реальные приложения не затронуты: автоматическое обнаружение пакетов правильно упорядочивает провайдеры.

rankbeam/laravel-seo распространяется под лицензией MIT.