balping/laravel-hashslug

提供在模型上使用Hashids功能的特质

2.3.0 2024-05-12 17:33 UTC

README

此包可用于使用Hashids隐藏真实模型ID以在URL中。给定应用、模型类和ID,哈希ID(短名)是确定性地生成的。另外,给定一个哈希ID(短名),也可以解码出真实ID。因此,不需要在数据库中存储额外的字段,ID在每次请求时进行解码。

动态生成URL

database -> id (1) -> hashslug (K4Nkd) -> url (http://localhost/posts/K4Nkd)

动态解码哈希ID并查找模型

url (http://localhost/posts/K4Nkd) -> hashslug (K4Nkd) -> id (1) -> database -> model

Hashslugs具有以下属性

  1. 保证hashslugs对于每个ID是唯一的
  2. 保证对于不同的模型,生成的哈希slug序列是不同的(ID为1的帖子将具有与ID为1的评论不同的hashslug)
  3. 保证对于不同的安装,生成的哈希slug序列是不同的(取决于.env文件中的app key)

需要注意的是,hashids不是随机的,也不是不可预测的。如果这成为问题,请不要使用此包。引用自hashids.org

如果你有一个关于“安全性”和“hashids”的问题或评论,请不要使用Hashids。

然而,虽然hashslug编码依赖于app key,但攻击者无法暴露它,因为它在传递给Hashids之前被sha256散列。你的app key是安全的。

安装

composer require balping/laravel-hashslug

版本

LaravelHashslug
5.4.*2.0.*
5.5 - 5.82.1.*
6.*2.1.*
7.*2.2.*
8.*2.3.*
9.*2.3.*
10.*2.3.*
11.*2.3.*

注意:此包需要PHP的BC MathGMP扩展才能工作。

用法

在希望具有哈希ID短名的模型上包含特质以隐藏数值递增ID。


use Illuminate\Database\Eloquent\Model;
use Balping\HashSlug\HasHashSlug;

class Post extends Model {
    use HasHashSlug;
}

之后,模型将添加slug()findBySlug($slug)findBySlugOrFail($slug)函数。

每次使用Laravel的帮助器生成URL时,都会使用哈希ID(默认长度为5个字符)而不是数值ID。

// routes/web.php
Route::resource('/posts', 'PostController');

// somewhere else
$post = Post::first();
echo action('PostController@show', $post);
// prints http://localhost/posts/K4Nkd

然后你可以通过短名解析模型。

// app/Http/Controllers/PostController.php

public function show($slug){
    $post = Post:findBySlugOrFail($slug);
  
    return view('post.show', compact('post'));
}

你还可以使用隐式模型绑定。你什么都不用做,它会自动工作!

只需输入模型类型提示,它们就会自动解析

// routes/web.php
Route::resource('/posts', 'PostController');

// app/Http/Controllers/PostController.php
public function show(Post $post){
    return view('post.show', compact('post'));
}

如果你需要显式模型绑定,这也是方便的

//app/Providers/RouteServiceProvider.php
public function boot(){
    parent::boot();

    Route::model('article', App\Post::class);
}

// routes/web.php
Route::resource('/articles', 'PostController');

// app/Http/Controllers/PostController.php
public function show(Post $post){
    return view('post.show', compact('post'));
}

URL中使用常规ID的用法

如果你想避免使用hashslug的隐式或显式模型绑定,并希望使用常规ID作为默认键,这也是可能的

// routes/web.php
Route::resource('/posts', 'PostController')->parameters([
    "posts" =>  "post:id"
]);

// or

Route::get('/posts/{post:id}', [PostController::class, 'show']);

// get URL

action('PostController@show', $post);

// app/Http/Controllers/PostController.php
public function show(Post $post){
    return view('post.show', compact('post'));
}

如果你在控制器中没有使用类型提示

// routes/web.php
Route::resource('/posts', 'PostController');

// or

Route::get('/posts/{id}', [PostController::class, 'show']);

// get URL

action('PostController@show', $post->id);

// app/Http/Controllers/PostController.php
public function show($post_id){
    $post = Post::findOrFail($post_id);
}

作为替代,你可以重写以下两个方法来实现相同的效果并回退到常规ID

class Post extends Model {
    use HasHashSlug;

    public function getRouteKeyName(){
        return parent::getRouteKeyName();
    }

    public function getRouteKey(){
        return parent::getRouteKey();
    }
}

自定义

哈希slug序列在每个模型和应用程序安装中的唯一性取决于拥有唯一的盐。

默认情况下,传递给Hashids的盐取决于.env文件中定义的应用程序key和模型的类名。

应用程序盐

要更改“应用程序盐”,创建文件config/hashslug.php然后添加以下代码

<?php

return [
    'appsalt' => 'your-application-salt'
];

请注意,您不需要配置此功能,但如果您不进行配置并且更改了您的应用程序密钥,则包含hashslugs的每个URL都将更改。例如,如果用户将此类URL设为书签,这可能会成为一个问题。

模型盐值

要使用自定义模型盐值而不是类名

class Post extends Model {
    use HasHashSlug;

    protected static $modelSalt = "posts";
}

如果您有多个同一模型的扩展类并且需要hashslugs保持一致,这样做可能是个好主意。

填充

更改slug的最小长度(默认:5)

class Post extends Model {
    use HasHashSlug;

    protected static $minSlugLength = 10;
}

您还可以通过将以下行添加到 config/hashslug.php 来全局设置slug的最小长度

    'minSlugLength' => 10

字母表

默认的字母表是 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890

这可以更改

class Post extends Model {
    use HasHashSlug;

    protected static $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
}

您还可以通过将以下行添加到 config/hashslug.php 来全局设置字母表

    'alphabet' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

前缀

您可以设置hashslug的自定义前缀

class Post extends Model {
    use HasHashSlug;

    protected static $hashSlugPrefix = 'post-';
}

这将返回形如 post-K4Nkd 的slug。

类似包及其区别

Laravel Hashids

提供一个外观,但没有内置路由。通过“连接”允许使用多个盐值。如果只需要为slugging模型使用hashids,则这是不必要的开销。

Eloquent-Hashids

在功能上与这个包基本相同,但使用上面的包会添加一个不必要的复杂层。使使用路由绑定成为可选的。

Laravel-Hashid

提供一个外观,类似于上面的外观,还提供一个类似这个包的特质。没有内置路由。没有提供测试。如果只需要为slugging模型使用hashids,则这是不必要的开销。

Hashids for Laravel 5

仅提供外观。不如第一个好,因为它只能有一个盐值。

Optimus

使用不同的混淆方法。仅提供外观(和类)。与路由或模型特质无关。据说它比hashids更快。

Laravel FakeID

类似于这个包,但基于Optimus构建。提供外观、特质以及特殊的路由功能。有良好的测试。

许可

这个包(特性和测试文件)在GPLv3许可下。