首页 > 解决方案 > 修改 Laravel 模型响应以使用不同的 ID

问题描述

我正在寻找某种“拦截”并在模型中的字段发送回客户端之前对其进行更改。我有一个 API,其端点类似于以下内容:

Route::get('users/{user}', 'Api\UserController@user');

我的应用程序使用vinkla/laravel-hashids,因此就客户端应用程序而言,要查询的 ID 应该类似于K6LJwKJ1M8,而不是1。目前,我可以查询提供哈希 ID 的用户,但响应返回的是数字/自动递增 ID。

例如,对于诸如/api/users/K6LJwKJ1M8我收到以下响应的查询:

{
    "id": 1,
    "address": null,
    "telephone": null,
    "name": "TestNameHere",
    "description": null,
    ...
}

Laravel 中是否有一种很好的方法可以修改所有在响应中返回的用户对象以使用 vinkla/laravel-hashids ID,而不是自动递增 ID?

理想情况下,上述响应将变为:

{
    "id": K6LJwKJ1M8,
    "address": null,
    "telephone": null,
    "name": "TestNameHere",
    "description": null,
    ...
}

我在想类似 using 的东西getRouteKey会起作用,但它不会改变在 JSON 响应中发送的对象。

例如

public function getRouteKey() {
    return Hashids::encode($this->attributes['id']);
}

如果有一个地方可以更改它会很好,因为我的应用程序有大约 40 条不同的路由,否则我需要“手动”更改(例如,在发送响应之前执行类似的操作$user->id = Hashids::encode($id)

标签: phplaravellaravel-7hashids

解决方案


您可以实现CastsAttributes 接口

实现此接口的类必须定义 get 和 set 方法。get 方法负责将数据库中的原始值转换为转换值,而 set 方法应将转换值转换为可以存储在数据库中的原始值。

在您的app目录中创建一个名为的目录Casts并创建一个名为的类UserCode

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use ...\Hashids;

class UserCode implements CastsAttributes
{
    public function get($model, $key, $value, $attributes)
    {
        return Hashids::encode($value);
    }

    public function set($model, $key, $value, $attributes)
    {
        return Hashids::decode($value);
    }
}

然后在您的用户模型中将强制转换添加UserCodeid值中:

use App\Casts\UserCode; // <--- make sure to import the class
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $casts = [
        'id' => UserCode::class,
    ];
}

然后,如果您愿意,User::find(1)->id您将获得散列值或访问/user/1它将返回具有散列 ID 的用户。信用

请注意,您无法通过散列 id 找到用户,除非您实现了某些东西,例如/user/hashed_id会给出 404。


推荐阅读