Ir al contenido

Migrar desde otros paquetes SEO de Laravel

Esta guía relaciona las API y formas de almacenamiento habituales con las dos piezas de Rankbeam: el trait HasSEO y saveSEO(). Para el paquete que guarda SEO por modelo hay un comando de importación. El esfuerzo concreto depende de tus personalizaciones.

¿Vienes de WordPress?

La guía Migrar desde WordPress (EN) describe el importador CSV y los lectores de bases de datos para Yoast y Rank Math.

Paquete de origenAlmacenamientoMigración
ralphjsmit/laravel-seoTabla polimórfica seophp artisan seo:import-from ralphjsmit y cambio de trait
artesaos/seotoolsNinguno en base de datos; ejecución y configuraciónSustituir llamadas por saveSEO() o getters calculados
spatie/*Builders de esquemas y sitemaps, sin tabla de metadatosConservar las funciones complementarias y migrar las demás

Solo ralphjsmit tiene aquí datos SEO en una tabla para importar en lote. Los otros generadores construyen etiquetas durante la petición: reemplaza sus llamadas por valores guardados en seo_meta o calculados.

Desde ralphjsmit/laravel-seo

Guarda una fila polimórfica por modelo en seo, con una estructura parecida a seo_meta. Esto permite una importación idempotente.

1. Instalar Rankbeam junto al paquete actual

bash
composer require rankbeam/laravel-seo
php artisan vendor:publish --tag=seo-config
php artisan vendor:publish --tag=seo-migrations
php artisan migrate

Ambos pueden coexistir durante la migración porque usan tablas (seo y seo_meta) y espacios de nombres distintos.

Una clave de configuración compartida

Un config/seo.php antiguo de ralphjsmit oculta la configuración de Rankbeam, ya que ambos usan la clave seo. Haz una copia, retíralo y publica el archivo de Rankbeam con php artisan vendor:publish --tag=seo-config.

2. Ejecutar el importador

bash
# Preview first — writes nothing
php artisan seo:import-from ralphjsmit --dry-run

# Then import for real
php artisan seo:import-from ralphjsmit

El importador lee seo, resuelve cada fila al modelo Eloquent real y escribe sus datos en seo_meta.

OpciónEfecto
--dry-runMostrar la importación prevista sin escribir.
--model="App\Models\Post"Limitar a una o varias clases; repetible.
--locale=frIdioma de destino; por defecto, el de la aplicación.
--table=legacy_seoLeer una tabla de origen con otro nombre.
--connection=legacyLeer mediante otra conexión de base de datos.
--limit=100Importar como máximo N filas para avanzar por etapas.
--overwriteReemplazar valores no vacíos; por defecto, solo completar campos vacíos.
--jsonInforme legible por máquina.
--forceOmitir la confirmación en scripts o CI.

Repetir el comando actualiza las mismas filas sin duplicarlas. Sin --overwrite, conserva los datos que ya hayas definido en Rankbeam. Activa esa opción solo si quieres reemplazarlos por los importados.

3. Cambiar el trait de los modelos

Sustituye el trait de ralphjsmit por el de Rankbeam. Algunos nombres de métodos cambian; la tabla leída pasa a ser seo_meta.

php
// Before
use RalphJSmit\Laravel\SEO\Support\HasSEO;

// After
use Rankbeam\Seo\Traits\HasSEO;

Traslada la lógica de getDynamicSEOData() a getSEOTitle(), getSEODescription(), getSEOImage(), getUrlForSEO() y getSEOAlternates(). Consulta el inicio rápido. Los valores explícitos se guardan con saveSEO():

php
$post->saveSEO([
    'title' => 'A hand-written SEO title',
    'description' => 'A hand-written meta description.',
    'canonical' => 'https://example.com/posts/my-post',
    'robots' => 'noindex, nofollow',
    'og_image' => 'https://example.com/og/my-post.jpg',
]);

Correspondencia de campos

Los campos se asignan de forma explícita, sin copiar columnas ausentes del esquema Core 3.

ralphjsmit seoRankbeam seo_metaNotas
model_type / model_idseoable_type / seoable_idSe calculan desde el modelo actual, no se copian literalmente.
titletitleLímite de columna de 70 caracteres; se informa de los recortes.
descriptiondescriptionLímite de 160 caracteres; se informa de los recortes.
canonical_urlcanonical
robotsrobotsLímite de 50 caracteres.
imageog_imagetwitter:image lo hereda mediante el resolvedor.
authorNo importadoCore 3 no tiene columna de autor en seo_meta; la autoría del artículo pertenece a los datos resueltos. Las filas afectadas se cuentan y notifican para que elijas un almacenamiento o cálculo adecuado.
id, created_at, updated_atNo importadosCampos estructurales del origen.

Por qué se recalcula el tipo polimórfico: cada fila se resuelve al modelo real y usa su getMorphClass() para obtener las claves seoable. Así respeta el morph map actual, aunque el paquete anterior guardara otra convención. Los modelos eliminados se notifican como omitidos y no crean relaciones huérfanas.

Entender el informe

Sin --json, se muestra una tabla y tres secciones de revisión:

  • Truncated: valores acortados para caber en seo_meta.
  • Not imported: columnas con datos, como author, sin destino en Core 3.
  • Skipped rows by reason: filas vacías, modelos eliminados o tipos que no se pueden resolver.

Verificar

bash
php artisan seo:audit            # confirm the imported metadata looks right

Una vez revisados los datos, puedes retirar ralphjsmit/laravel-seo y eliminar la antigua tabla seo.

Desde artesaos/seotools

Este paquete genera etiquetas en ejecución mediante SEOMeta, OpenGraph, TwitterCard y JsonLd, normalmente desde un controlador, con valores iniciales en config/seotools.php. No hay una tabla por modelo que importar: mueve esas llamadas a valores guardados o calculados.

Llamada artesaos/seotoolsEquivalente Rankbeam
SEOMeta::setTitle($t)saveSEO(['title' => $t]) o getSEOTitle()
SEOMeta::setDescription($d)saveSEO(['description' => $d]) o getSEODescription()
SEOMeta::setCanonical($u)saveSEO(['canonical' => $u]) o getUrlForSEO()
SEOMeta::addKeyword(...)saveSEO(['focus_keywords' => [...]]), consulta auditoría
OpenGraph::setTitle / setDescription / addImagesaveSEO(['og_title' => …, 'og_description' => …, 'og_image' => …])
TwitterCard::setType / setTitle / setImagesaveSEO(['twitter_card' => …, 'twitter_title' => …, 'twitter_image' => …])
JsonLd::setType(...) / JsonLdMultiGrafo JSON-LD (EN)
Valores de config/seotools.phpconfig/seo.php y prioridad del resolvedor
{!! SEO::generate() !!} en el layout@seo($model), consulta Blade (EN)

En lugar de fijar etiquetas en cada controlador, guarda los datos una vez por modelo en seo_meta y deja que el resolvedor los emita. Los valores globales pasan a la configuración (EN). Las páginas estáticas por ruta usan @seoForRoute().

Desde paquetes Spatie

No existe un paquete de almacenamiento SEO spatie/laravel-seo. Los paquetes Spatie habituales son builders complementarios que puedes conservar o sustituir por separado:

  • spatie/schema-org: builder fluent de JSON-LD. El grafo Rankbeam (EN) ofrece builders tipados Article, FAQPage, Product, BreadcrumbList, LocalBusiness y Organization, guardados en seo_meta.schema_jsonld y emitidos sin duplicados. Pasa la salida ->toArray() de objetos existentes a saveSEO(['schema_jsonld' => $array]) o reescríbelos con los builders de Rankbeam.
  • spatie/laravel-sitemap: el registro de Rankbeam se basa en él. Registra los modelos como fuentes de un sitemap combinado o conserva tu sitemap actual y desactiva la ruta Rankbeam.

Para romanzipp/laravel-seo, otro generador en ejecución, usa el mismo patrón que con artesaos: reemplaza setTitle y addMeta por saveSEO() o getters calculados.

Ampliar el importador

seo:import-from utiliza un registro de implementaciones de Rankbeam\Seo\Importing\Contracts\Importer. Añadir una fuente no exige modificar el comando. Incluye ralphjsmit y los importadores WordPress (EN) wordpress-csv, yoast y rank-math. Registra uno propio en un proveedor de servicios:

php
use Rankbeam\Seo\Importing\ImporterRegistry;

$this->app->afterResolving(ImporterRegistry::class, function (ImporterRegistry $registry) {
    $registry->register('my-source', \App\Seo\MyImporter::class);
});

rankbeam/laravel-seo se distribuye bajo la licencia MIT.