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

Приоритеты резолвера

Каждое итоговое значение SEO — заголовок, описание, канонический URL, robots, изображения — формируется SEOResolver при объединении шести слоёв. Более высокие слои имеют приоритет, а null никогда не перезаписывает значение нижнего слоя, поэтому каждая страница всегда получает осмысленные значения.

Шесть слоёв

От самого нижнего (присутствует всегда) к самому верхнему (всегда побеждает):

СлойИсточникТипичное применение
1Конфигурация сайтаconfig/seo.php (site_name, title_suffix, default_og_image, default_robots, …)Общие для бренда значения по умолчанию
2Глобальные значения по умолчанию в БДСтроки seo_defaults без типа моделиРедактируемые значения для всего сайта без развёртывания
3Значения по умолчанию для типа моделиСтроки seo_defaults, привязанные к классу модели«Все товары получают это OG-изображение»
4Значения по умолчанию для маршрутаСтроки seo_defaults, привязанные к имени маршрутаСтатические страницы (home, contact) без модели
5Вычисляемые значенияПолучаются из собственных атрибутов моделиРезервный заголовок из title, описание из excerpt/body, …
6Явные значенияСтрока seo_meta модели (saveSEO())Значения, заданные редакторами вручную
php
use Rankbeam\Seo\Facades\SEO;

$seo = SEO::resolve($post);          // model page: layers 1-3 + 5-6
$seo = SEO::forRoute('contact');     // route page: layers 1-2 + 4

Результат — неизменяемый объект-значение SEOData, который используют все средства вывода (Blade, массив, Inertia).

Вычисляемые резервные значения (слой 5)

Если явное значение отсутствует, резолвер получает его из модели:

  • Заголовок — атрибут title/name модели.
  • Описание — первый атрибут из seo.computed.description_fields (цепочка по умолчанию: excerpt, summary, description, intro, lead, teaser, content, body, text, article), содержащий осмысленный текст. HTML удаляется, сущности декодируются, а текст обрезается по границе слова (seo.computed.description_max_length, по умолчанию 160 — без многоточия).
  • Robots — из метода модели getSEORobots() или атрибута is_indexable (см. управление robots и возможностью индексации).
  • Значения из URL — канонический URL и og:url из getUrlForSEO().

Управление robots и возможностью индексации

Настройка noindex для отдельной модели уже встроена — дополнительные пакеты или специальные столбцы не нужны. Трейт HasSEO не объявляет метод robots (он необязателен), поэтому эту возможность легко не заметить. Однако резолвер уже учитывает три источника, начиная с самого приоритетного:

ПриоритетИсточникПример
1Явное seo_meta.robots$page->saveSEO(['robots' => 'noindex,follow'])
2Метод getSEORobots(): ?string в моделиВернуть 'noindex, nofollow' или null, чтобы перейти к следующему источнику
3Атрибут is_indexable (столбец или аксессор)Значение, приводимое к false, ⇒ noindex, nofollow; приводимое к true, ⇒ index, follow
php
class Page extends Model
{
    use HasSEO;

    // Option A: let the resolver derive robots from a boolean flag.
    //   Schema::table('pages', fn ($t) => $t->boolean('is_indexable')->default(true));

    // Option B: compute it from your own state.
    public function getSEORobots(): ?string
    {
        return $this->status === 'draft' ? 'noindex, nofollow' : null;
    }
}

// Option C: set it explicitly per page (wins over A and B).
$page->saveSEO(['robots' => 'noindex, follow']);

Что фактически выводится

Перед попаданием в <head> полученная директива проходит политику вывода: тег <meta name="robots"> выводится только тогда, когда директива отличается от default_robots (по умолчанию index,follow). Поэтому:

  • страница, разрешающая индексацию (результат index, follow), не выводит тег robots — его отсутствие поисковый робот трактует как index,follow;
  • страница, запрещающая индексацию, выводит <meta name="robots" content="noindex, nofollow">;
  • любая отличающаяся директива (noindex, max-snippet:-1, unavailable_after, …) выводится без изменений, с сохранением введённых пробелов.

Задайте seo.robots.emit_default = true, чтобы тег выводился всегда. Подробности — в политике вывода robots.

Политики после определения итоговых значений

Они применяются независимо от того, какой слой задал значение:

  • Суффикс заголовкаtitle_suffix добавляется, если итоговый заголовок ещё не заканчивается им. Если шаблон значения по умолчанию для маршрута уже содержит бренд, завершите шаблон суффиксом, чтобы избежать «Brand — X | Brand».
  • Удаление параметров запроса из канонического URL — у вычисленных канонических URL (URL модели / текущий URL) удаляется строка запроса, кроме ключей из canonical.query_whitelist (например, page для архивов с пагинацией), которые сохраняются; явно заданные канонические URL сохраняются без изменений.
  • Абсолютные URL изображений для соцсетейog:image и twitter:image всегда выводятся как абсолютные URL (этого требует спецификация Open Graph), даже если сохранён относительный путь.

Как узнать, какой слой победил

Пакет Filament показывает это для каждого поля (Вручную / Из контента / Значение по умолчанию для типа модели / Глобальное значение по умолчанию / Конфигурация сайта / Получено из URL). В коде SEOWarningEvaluator предоставляет такое же различие между ручным и резервным значением, чтобы вы могли создавать собственные индикаторы в панели администратора.

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