修改 Laravel 模型响应以使用不同的 ID
Modify Laravel model response to use different ID
我希望在将模型发送回客户端之前进行某种“拦截”并更改模型中的字段。我有一个 API 端点类似于以下内容:
Route::get('users/{user}', 'Api\UserController@user');
我的应用程序使用vinkla/laravel-hashids,所以就客户端应用程序而言,要查询的ID 应该是K6LJwKJ1M8
,而不是1
。目前我可以查询提供 hash-id 的用户,但响应返回 numeric/auto-incrementing 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,
...
}
我在想使用 getRouteKey
之类的东西会起作用,但它不会更改 JSON 响应中发送的对象。
例如
public function getRouteKey() {
return Hashids::encode($this->attributes['id']);
}
如果有一个地方可以改变这个就好了,因为我的应用程序有大约 40 条不同的路线,否则我需要“手动”改变(例如,在发送响应之前做一些像 $user->id = Hashids::encode($id)
)
您可以使用 API 资源
https://laravel.com/docs/7.x/eloquent-resources#introduction
API Resource acts as a transformation layer that sits between your
Eloquent models and the JSON responses that are actually returned to
your application's users.
您可以为用户创建一个 API 资源,并在响应中 return 用户的任何地方使用它。
Api 资源给了你更多的控制权,你可以操纵你想要的任何字段,使用几个字段的组合发送一些额外的字段,更改你想要在响应中的字段的名称(xyz => $this->name
)
用户资源
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
//You can access model properties directly using $this
return [
'id' => Hashids::encode($this->id),
"address": $this->address,
"telephone": $this->telephone,
"name": $this->name,
"description": $this->description,
...
];
}
}
然后在任何地方 return 一个用户实例。
控制器
// $user is a User Model Instance.
return new UserResource($user);
如果你有 collection
// $users is a collection of User Model instances.
return UserResource::collection($users);
UserResource 将应用于您 collection 中的每个模型实例,然后 return 作为您的 JSON 响应发送给您。
要实现您想要的效果,在您的模型中,您必须使用 set getIncrementing
to false
并确保 getKeyType
设置为 string
。
class YourModel extends Model
{
public function getIncrementing()
{
return false;
}
public function getKeyType()
{
return 'string';
}
}
如果您使用的是 uuid
并且迁移文件中包含以下内容,则以上内容有效:
$table->uuid('id')->primary();
您可能必须找到一种方法来修改包以使用此方法。
您可以实施 CastsAttributes interface:
Classes that implement this interface must define a get and set method. The get method is responsible for transforming a raw value from the database into a cast value, while the set method should transform a cast value into a raw value that can be stored in the database.
在您的 app
目录中创建一个名为 Casts
的目录并创建一个名为 UserCode
:
的 class
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);
}
}
然后在您的用户模型中将 UserCode
添加到 id
值:
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
,它将 return 具有散列 ID 的用户。 credit.
请注意,您无法通过散列 ID 找到用户,除非您实施了某些操作,例如/user/hashed_id
将给出 404。
我希望在将模型发送回客户端之前进行某种“拦截”并更改模型中的字段。我有一个 API 端点类似于以下内容:
Route::get('users/{user}', 'Api\UserController@user');
我的应用程序使用vinkla/laravel-hashids,所以就客户端应用程序而言,要查询的ID 应该是K6LJwKJ1M8
,而不是1
。目前我可以查询提供 hash-id 的用户,但响应返回 numeric/auto-incrementing 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,
...
}
我在想使用 getRouteKey
之类的东西会起作用,但它不会更改 JSON 响应中发送的对象。
例如
public function getRouteKey() {
return Hashids::encode($this->attributes['id']);
}
如果有一个地方可以改变这个就好了,因为我的应用程序有大约 40 条不同的路线,否则我需要“手动”改变(例如,在发送响应之前做一些像 $user->id = Hashids::encode($id)
)
您可以使用 API 资源 https://laravel.com/docs/7.x/eloquent-resources#introduction
API Resource acts as a transformation layer that sits between your Eloquent models and the JSON responses that are actually returned to your application's users.
您可以为用户创建一个 API 资源,并在响应中 return 用户的任何地方使用它。
Api 资源给了你更多的控制权,你可以操纵你想要的任何字段,使用几个字段的组合发送一些额外的字段,更改你想要在响应中的字段的名称(xyz => $this->name
)
用户资源
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
//You can access model properties directly using $this
return [
'id' => Hashids::encode($this->id),
"address": $this->address,
"telephone": $this->telephone,
"name": $this->name,
"description": $this->description,
...
];
}
}
然后在任何地方 return 一个用户实例。
控制器
// $user is a User Model Instance.
return new UserResource($user);
如果你有 collection
// $users is a collection of User Model instances.
return UserResource::collection($users);
UserResource 将应用于您 collection 中的每个模型实例,然后 return 作为您的 JSON 响应发送给您。
要实现您想要的效果,在您的模型中,您必须使用 set getIncrementing
to false
并确保 getKeyType
设置为 string
。
class YourModel extends Model
{
public function getIncrementing()
{
return false;
}
public function getKeyType()
{
return 'string';
}
}
如果您使用的是 uuid
并且迁移文件中包含以下内容,则以上内容有效:
$table->uuid('id')->primary();
您可能必须找到一种方法来修改包以使用此方法。
您可以实施 CastsAttributes interface:
Classes that implement this interface must define a get and set method. The get method is responsible for transforming a raw value from the database into a cast value, while the set method should transform a cast value into a raw value that can be stored in the database.
在您的 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);
}
}
然后在您的用户模型中将 UserCode
添加到 id
值:
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
,它将 return 具有散列 ID 的用户。 credit.
请注意,您无法通过散列 ID 找到用户,除非您实施了某些操作,例如/user/hashed_id
将给出 404。