artisanpack-ui/seo
A Laravel package for adding SEO controls to your application. It helps manage page titles, meta descriptions, and other search metadata through a simple, configurable interface, making it easier to keep pages search-friendly and consistent.
Architecture fit: Laravel-native package extending Eloquent morph relations (seoable, sitemapable) and service-provider filters. v1.8.0 adds a resolver abstraction (MorphModelResolver, ResolvesMorphModels, ResolvableMorphTo) to support morph types that are not class names—e.g., shared models with getMorphClass() values like App\Models\Record:products. This aligns with Laravel apps using morph maps, multi-tenant schemas, or one model spanning multiple tables. The change is additive and does not replace existing class-name resolution.
Integration feasibility: Low-to-moderate. For standard class-name morphs, the upgrade is transparent. For non-class morph types, teams must register the ap.seo.resolveMorphModel filter to map type strings to model instances. No database migration is indicated. The cache key change from meta:<class>:<id> to meta:<class>:<table>:<id> is behaviorally compatible but causes a one-time cold cache. Hreflang cache clearing now correctly handles morph-map aliases and resolver-backed types.
Technical risk: Primary risk is misconfiguration or omission of the resolver filter for custom morph types, which would preserve the previous Class "…" not found failure for those types. A resolver returning an incorrect model instance could attach SEO/sitemap data to the wrong record. The cache key change improves correctness but temporarily increases cache misses and may increase cache entry count because keys are now table-scoped. Lazy and eager loading are addressed, reducing relation-loading risk.
Key questions: Do we use non-class morph types or morph-map aliases? Are all custom morph types documented and covered by the resolver filter? Do we have tests for with('seoable') and with('sitemapable') under those types? What is the cache footprint impact of table-scoped keys? Which Laravel/PHP versions does v1.8.0 support? Do we need a cache warmup after deploy?
Stack fit: Fits Laravel applications already using Eloquent polymorphic relations for SEO metadata, sitemaps, and hreflang. The new resolver layer is idiomatic Laravel—service-provider filter plus relation trait—so it should integrate without architectural changes. Teams using standard class-name morphs can treat this as a patch-level upgrade.
Migration path: Update via Composer to v1.8.0. No schema migration is indicated. If the application uses custom morph types, add and register the ap.seo.resolveMorphModel filter in a service provider before relying on seoable/sitemapable. Run the test suite against SEO meta, sitemap generation, and hreflang output. Clear application cache after deploy because cache keys change; existing entries will miss once and rebuild.
Compatibility: Backward compatible for types the filter does not resolve—they behave as before. The cache key format change is transparent to callers but changes cache storage. Hreflang cache clearing is fixed for aliases and resolver-backed types. Verify compatibility with the app’s Laravel version and cache driver, especially if using tagged caches or shared cache stores.
Sequencing: 1) Upgrade in staging and confirm Composer constraints. 2) Identify all morph types used by seoable and sitemapable, including morph-map aliases and shared-model types. 3) Implement and register the resolver filter for non-class types. 4) Add regression tests for lazy loading and eager loading of both relations. 5) Clear caches and monitor miss rate/cache size after deploy. 6) Roll out to production with a short observation window.
Maintenance: The resolver filter becomes a small configuration surface that must stay in sync with morph maps and shared-model naming. Whenever a new morph alias or shared-model type is introduced, update the filter and tests. Table-scoped cache keys reduce cross-table contamination but mean cache invalidation should include table context. Hreflang cache clearing is more reliable for aliases, lowering manual cache-clear support.
Support: Standard class-name morph users should see no change. Support burden is concentrated in custom morph types; provide a runbook covering resolver registration, expected type strings, and cache-clear steps. Document that unresolved types intentionally retain legacy behavior, so a missing filter looks like the old bug rather than a new regression.
Scaling: Table-scoped cache keys can increase the number of cache entries, especially for models stored across many tables. Plan for cache capacity and eviction behavior. The resolver adds a small per-relation lookup, but it prevents class-instantiation failures and supports eager loading. Hreflang cache clearing correctness improves operational predictability at scale.
Failure modes: Missing or incorrect resolver filter → Class "…" not found persists or the wrong model is resolved. Resolver returns an unsupported type → falls back to legacy behavior. Cache key change → cold cache and temporary load increase. Hreflang cache not cleared if resolver cannot resolve the type. Misconfigured morph map or renamed table → stale or fragmented cache until cleared.
Ramp-up: Low for Laravel developers. TPM should allocate time for morph-type inventory, resolver configuration, and regression testing of SEO/sitemap/hreflang paths. A short pairing session on Laravel morph maps and service-provider filters is sufficient for most teams.
How can I help you explore Laravel packages today?