salah3id/laravel-slugs

在保存 Eloquent 模型时生成 slugs

3.3.0 2022-01-13 11:33 UTC

README

Latest Version on Packagist MIT Licensed GitHub Workflow Status Total Downloads

此包提供了一种特性,可以在保存任何 Eloquent 模型时生成唯一的 slug。

$model = new EloquentModel();
$model->name = 'activerecord is awesome';
$model->save();

echo $model->slug; // outputs "activerecord-is-awesome"

slug 是通过 Laravel 的 Str::slug 方法生成的,其中空格被转换为 '-'。

Spatie 是一家位于比利时安特卫普的网页设计公司。您可以在我们的网站上找到我们所有开源项目的概述 在此

支持我们

我们投入了大量资源来创建 最佳类别的开源包。您可以通过 购买我们的付费产品之一 来支持我们。

我们非常感谢您从您的家乡寄给我们一张明信片,说明您正在使用我们的哪些包。您可以在我们的 联系页面 上找到我们的地址。我们将所有收到的明信片发布在我们的 虚拟明信片墙 上。

安装

您可以通过 composer 安装此包

composer require spatie/laravel-sluggable

用法

您的 Eloquent 模型应使用 Spatie\Sluggable\HasSlug 特性和 Spatie\Sluggable\SlugOptions 类。

该特性包含一个抽象方法 getSlugOptions(),您必须自行实现。

您的模型迁移应有一个字段来保存生成的 slug。

以下是实现此特性的示例

namespace App;

use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasSlug;

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug');
    }
}

及其迁移

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateYourEloquentModelTable extends Migration
{
    public function up()
    {
        Schema::create('your_eloquent_models', function (Blueprint $table) {
            $table->increments('id');
            $table->string('slug'); // Field name same as your `saveSlugsTo`
            $table->string('name');
            $table->timestamps();
        });
    }
}

在路由中使用 slugs

要在路由中使用生成的 slug,请记住使用 Laravel 的 隐式路由模型绑定

namespace App;

use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasSlug;

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug');
    }

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }
}

使用多个字段创建 slug

想要使用多个字段作为 slug 的基础?没问题!

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom(['first_name', 'last_name'])
        ->saveSlugsTo('slug');
}

自定义 slug 生成

您还可以将一个 callable 传递给 generateSlugsFrom

默认情况下,该包将通过对已存在的 slug 追加 '-' 和一个数字来生成唯一的 slug。

您可以通过调用 allowDuplicateSlugs 来禁用此行为。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->allowDuplicateSlugs();
}

限制 slug 的长度

您还可以为创建的 slug 设置最大大小限制

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->slugsShouldBeNoLongerThan(50);
}

由于添加了后缀以使其唯一,slug 可能略长于指定的值。

您还可以通过调用 usingSeparator 使用自定义分隔符

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->usingSeparator('_');
}

设置 slug 语言

要设置 Str::slug 使用的语言,您可以调用 usingLanguage

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->usingLanguage('nl');
}

覆盖 slugs

您还可以通过将其设置为与生成的 slug 不同的值来覆盖生成的 slug。

$model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name";
$model->slug = 'my-custom-url';
$model->save(); //slug is now "my-custom-url";

在某些条件下防止生成 slugs

如果您不希望在模型处于某种状态时创建 slug,您可以使用 skipGenerateWhen 函数。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->skipGenerateWhen(fn () => $this->state === 'draft');
}

防止在创建时生成 slugs

如果您不希望在模型最初创建时创建 slug,您可以设置 doNotGenerateSlugsOnCreate() 函数。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->doNotGenerateSlugsOnCreate();
}

防止 slug 更新

类似地,如果您想防止在模型更新时更新 slug,请调用 doNotGenerateSlugsOnUpdate()

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->doNotGenerateSlugsOnUpdate();
}

这可以有助于创建在您明确想要更改之前不会更改的永久链接。

$model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name";
$model->save();

$model->name = 'changed name';
$model->save(); //slug stays "my-name"

重新生成 slugs

如果您想显式更新模型的 slug,可以在模型上随时调用 generateSlug() 来根据您的其他选项生成 slug。别忘了调用 save() 来将模型保存到数据库中,以持久化更新。

防止覆盖

您可以选择防止 slug 被覆盖。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->preventOverwrite();
}

使用作用域

如果您有一个应该考虑的全局作用域,您也可以使用 extraScope 定义它。例如,如果您有一个包含多个网站页面的页面表,并且每个网站都有自己的唯一 slug。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->extraScope(fn ($builder) => $builder->where('scope_id', $this->scope_id));
}

设置 slug 后缀起始索引

默认情况下,后缀索引从 1 开始,您可以设置起始数字。

public function getSlugOptions() : SlugOptions
{
    return SlugOptions::create()
        ->generateSlugsFrom('name')
        ->saveSlugsTo('slug')
        ->startSlugSuffixFrom(2);
}

与 laravel-translatable 集成

您可以使用此包与 laravel-translatable 一起使用,为每个区域生成一个 slug。您必须使用 HasTranslatableSlug 特性,而不是使用 HasSlug 特性,并将 slug 字段的名称添加到 $translatable 数组中。对于从单个字段 多个字段生成的 slug,您无需更改其他任何内容。

namespace App;

use Spatie\Sluggable\HasTranslatableSlug;
use Spatie\Sluggable\SlugOptions;
use Spatie\Translatable\HasTranslations;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasTranslations, HasTranslatableSlug;

    public $translatable = ['name', 'slug'];

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug');
    }
}

对于从可调用函数生成的 slug,您需要使用 createWithLocales 方法实例化 SlugOptions。现在,可调用函数接受两个参数而不是一个。现在可以使用 $model$locale 来生成 slug。

namespace App;

use Spatie\Sluggable\HasTranslatableSlug;
use Spatie\Sluggable\SlugOptions;
use Spatie\Translatable\HasTranslations;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasTranslations, HasTranslatableSlug;

    public $translatable = ['name', 'slug'];

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::createWithLocales(['en', 'nl'])
            ->generateSlugsFrom(function($model, $locale) {
                return "{$locale} {$model->id}";
            })
            ->saveSlugsTo('slug');
    }
}

隐式路由模型绑定

您还可以在控制器中使用 Laravel 的 隐式路由模型绑定 来自动解析模型。要使用此功能,请确保 slug 列与 routeNameKey 匹配。
目前,只有一些数据库类型支持 JSON 操作。有关支持 JSON 的数据库的更多信息,请参阅 Laravel 文档

namespace App;

use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;
use Illuminate\Database\Eloquent\Model;

class YourEloquentModel extends Model
{
    use HasTranslations, HasTranslatableSlug;

    public $translatable = ['name', 'slug'];

    /**
     * Get the options for generating the slug.
     */
    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug');
    }

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }
}

通过 slug 查找模型

为了方便,您可以使用别名 findBySlug 来检索模型。查询将对比在定义 SlugOptions 时传递给 saveSlugsTo 的字段。

$model = Article::findBySlug('my-article');

findBySlug 也可以接受一个名为 $columns 的第二个参数,就像默认的 Eloquent find 方法一样。

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

测试

composer test

贡献

有关详细信息,请参阅 CONTRIBUTING

安全性

如果您发现有关安全性的错误,请通过 security@spatie.be 发送电子邮件,而不是使用问题跟踪器。

致谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件