rvzug/laravel-seo-urls

当模型保存时,提供自动创建SEO-urls和重定向的功能

v0.1.0 2024-03-29 19:27 UTC

This package is auto-updated.

Last update: 2024-09-29 20:44:54 UTC


README

使用符合SEO规则的sluggable SEO-urls来为模型定义,尊重SEO原则,如规范URL原则,避免重复内容,并跟踪模型的SEO历史URL

正在进行中:这份文档/README是一个快速草案,旨在突出大部分功能。它应该已经涵盖了此包的基本内容。

简介

使用slug是网络应用程序中相对常见的功能,用于定义美观且易于阅读的URL。Laravel本身允许在route model binding中使用slug,自定义键。此外,还有许多包可以实现将slug作为URL指针指向正确模型的功能。特别是使用Spatie Sluggable包时,可以创建强大的sluggable URL。

这很好,但从搜索引擎优化(SEO)的角度来看,当slug发生变化时存在潜在风险:旧URL不再可达,会导致断链数量增加。如果处理不当,可能会导致SEO惩罚增加和搜索排名下降。

为了防止这种情况,通常的做法是将slug保留为'永久链接',并永远不更新slug。但是,当你故意想要更新slug时,例如当你犯了一个错误,或者你允许最终用户控制slug时,就没有办法修复它。如果你在创建URL后立即这样做,那很好。但是,如果在几周后发现了一个错误,或者决定更改slug更好,你必须手动创建一个重定向。

此包可以实现以下功能:

  • 在多个模型上创建(和处理)slug
  • 添加更改slug的能力
  • 保留旧slug的历史记录
  • 自动将旧URL-slug重定向到最新的slug
  • 提供多个辅助函数来检索正确的SEO-urls

路由原则

此包假设你已经为模型创建了'非slug路由'。例如,显示一个主题,通常的做法是创建一个处理URL domain.com/topic/{id} 的路由。

例如

Route::get('/topic/{id}', [TopicController::class, 'show'])->name('topic.show');

通常,TopicController::show()方法将返回一个包含主题视图的响应。该包使用这些路由作为内部路由将用户转发到正确的视图。

此包还假设这些路由上定义了路由名称。

使用此包时,你必须保留这些路由。当SEO URL用于导航到视图时,它将应用程序内部的请求转发到原始定义的路由,同时保留浏览器的SEO URL

domain.com/why-you-should-avoid-broken-links >>-转发->> domain.com/topic/123

浏览器将显示: domain.com/why-you-should-avoid-broken-links 使用内部路由: /topic/123

重定向旧SEO URL

如果使用了旧的{slug},此包将重定向浏览器到最新的正确{slug}。然后转发到内部路由以显示正确的视图

domain.com/why-yuo-should-avoid-brken-lnk >>-301->> domain.com/why-you-should-avoid-broken-links >>-转发->> domain.com/topic/123

浏览器将显示: domain.com/why-you-should-avoid-broken-links 使用内部路由: /topic/123

禁用内部路由

仍然可以浏览到内部URL,例如 domain.com/topic/123。主题将被显示。如果您不希望这种行为,可以向路由添加提供的 InterceptInternalRoute 中间件

use Rvzug\LaravelSeoUrls\Http\Middleware\InterceptInternalRoute;

// ...

Route::get('topic/{id}', [TopicController::class, 'show'])
    ->name('topic.show')
    ->middleware(InterceptInternalRoute::class)

此中间件将 拦截 内部路由,将浏览器中显示的 seo-url 重定向,然后再次 转发 到内部路由以显示视图。

浏览器将显示: domain.com/why-you-should-avoid-broken-links 使用内部路由: /topic/123

它将使用路由名和提供的路由参数(在本例中:id)来搜索相应的 seo-url。 如果没有找到模型,则返回 ModelNotFoundException / 404错误

防止重复内容惩罚

如果您想保留内部路由的默认行为,即 domain.com/topic/123 只显示视图而不重定向到 seo-url,您应该在 blade-模板的 <head> 部分实现以下代码片段

<link rel="canonical" href="{{ cannonicalUrl($model) }}" />

有关规范 URL 原则和避免重复内容惩罚的更多信息,请参阅 Google Search Central

文档

安装

要求包: composer require rvzug/laravel-seo-urls

发布迁移文件: php artisan vendor:publish ...

运行迁移以将 seo_urls 表添加到您的数据库: php artisan migrate

配置

此包默认情况下无需更改配置即可使用。但如果您想更改默认配置,可以发布包配置文件: php artisan vendor:publish ...

默认配置

快速入门

要使用 SEO-urls,您应该将以下三个代码片段实现到您的应用程序中

  1. 将 HasSeoUrls-trait 添加到应生成 seo-urls 的模型中
// Models/Topic.php

use Rvzug\LaravelSeoUrls\Models\Traits\HasSeoUrls

class Topic extends Model
{
    use HasSeoUrls;
    ...
}
  1. 在模型上实现 getRouteName()-方法,以定义详细路由应指向哪个路由
    protected function getRouteName()
    {
        return 'topics.show';
    }
  1. 将 seo-url 路由添加到您的路由中,任何主页路由之后(定义的任何 回退路由 之前)
// routes/web.php

// Default home route
Route::get('/', function () { // Original home route
    return view('welcome');
});

// Added route to handle slugs
Route::any('/{slug}', function (string $slug) {
    return SeoUrls::handleSlug($slug);
})->name('seo');

// Fallback route (@see: https://laravel.net.cn/docs/11.x/routing#fallback-routes)
Route::fallback(function () {
    // ...
});
// ...

如果您计划在 seo-urls 中使用斜杠(/),则必须将 ->where('slug', '.*') 方法链接到 slug 路由。请参阅 Laravel 文档

Route::any('/{slug}', function (string $slug) {
    return SeoUrls::handleSlug($slug);
})->where('slug', '.*')->name('seo');

在此阶段,当创建使用该特质的模型时,它将可在 URL 上使用: domain.com/{model}-{id}

模型

您可以通过在模型中添加 generateSeoUrlSlug()-方法来更改生成的 slug。

use Illuminate\Support\Str;

protected function generateSeoUrlSlug(): string
{
    return Str::slug($this->attributes['title']);
}

该方法应返回一个字符串,该字符串定义了您想要的 slug。您可以利用模型的属性,如 $this->title。有时甚至更好;使用属性数组 $this->attributes['title']

示例:基于日期的 slug

还可以创建一个漂亮的基于日期的 seo-url,例如 /2024/03/01/why-you-should-use-date-pages

use Carbon\Carbon;
use Illuminate\Support\Str;

protected function generateSeoUrlSlug(): string
{
    return Str::slug(sprintf('%s/%s/%s/%s', 
        (new Carbon($this->attributes['created_at']))->format('Y'),
        (new Carbon($this->attributes['created_at']))->format('m'),
        (new Carbon($this->attributes['created_at']))->format('d'),
        $this->attributes['title'])
    );
}

保存模型

当保存模型时,slug 将根据以下优先级生成

  1. 如果您在调用 $model->save() 之前设置了 $model->slug,则将使用此设置
  2. 如果添加了 generateSeoUrlSlug() 将用作回退
  3. 包回退是 {{model_name}}-{{primary-key}}

禁用自动保存 seo-url

如果您在保存模型时不希望保存 seo-url,请将 $model->dontUpdateSeoUrl = true; 属性设置为 true

SeoUrl 关系

HasSeoUrls-trait 为您的模型添加了一个关系 $model->seoUrls()。这包含一个 SeoUrl 模型的集合。此模型具有以下属性

* model_type/model_id 是一个 多态关系 到创建 seo-url 的模型

使用 Eloquent 事件 在保存父模型时保存 seo-url 关系。