Измените ответ модели Laravel, чтобы использовать другой идентификатор - PullRequest
2 голосов
/ 01 августа 2020

Я ищу своего рода «перехват» и изменение поля в модели, прежде чем оно будет отправлено обратно клиенту. У меня есть API с конечными точками, подобными следующему:

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

Мое приложение использует vinkla / laravel -hashids , поэтому, что касается клиентского приложения, идентификатор для запрос должен иметь вид K6LJwKJ1M8, а не 1. В настоящее время я могу запросить пользователя, предоставившего ha sh -id, но ответ возвращается с числовым / автоматически увеличивающимся идентификатором.

например. Для такого запроса, как /api/users/K6LJwKJ1M8, я получаю следующий ответ :

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

Есть ли хороший способ в Laravel, что я мог бы изменить все пользовательские объекты, возвращаемые в ответах, чтобы использовать идентификатор vinkla / laravel -hashids вместо автоматически увеличивающегося идентификатора?

В идеале ответ должен выглядеть так:

{
    "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))

Ответы [ 3 ]

1 голос
/ 01 августа 2020

Для достижения желаемого в вашей модели вам нужно будет установить getIncrementing на false и убедиться, что getKeyType установлено на string.

class YourModel extends Model
{
    public function getIncrementing()
    {
        return false;
    }

    public function getKeyType()
    {
        return 'string';
    }
}

Вышеупомянутое будет работать, если вы использовали uuid и в вашем файле миграции есть следующее:

$table->uuid('id')->primary();

Вам, вероятно, придется найти способ изменить пакет, чтобы использовать этот подход.

1 голос
/ 01 августа 2020

Вы можете реализовать интерфейс CastsAttributes :

Классы, реализующие этот интерфейс, должны определять методы получения и установки. Метод 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);
    }
}

Затем в вашей пользовательской модели добавьте приведение 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, он вернет пользователя с хешированным идентификатором. кредит .

Обратите внимание, что вы не сможете найти пользователя по хешированному идентификатору, если не реализовали что-то, например, /user/hashed_id даст 404.

1 голос
/ 01 августа 2020

Вы можете использовать ресурсы API https://laravel.com/docs/7.x/eloquent-resources#introduction

Ресурс API действует как уровень преобразования, который находится между вашими моделями Eloquent и ответами JSON, которые фактически возвращаются в пользователей вашего приложения.

Вы можете создать ресурс API для пользователя и использовать его везде, где вы возвращаете пользователя в ответ.

Ресурсы Api дают вам гораздо больше контроля , вы можете манипулировать любым полем, которое хотите, отправить несколько дополнительных полей, используя комбинацию нескольких полей, изменить имя полей, которые вы хотите в своем ответе (xyz => $this->name)

UserResource

<?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,
             ...
        ];
    }
}

И затем, куда бы вы ни захотели вернуть экземпляр пользователя.

Контроллер

// $user is a User Model Instance.

return new UserResource($user); 

Если у вас есть коллекция

// $users is a collection of User Model instances.

return UserResource::collection($users);

UserResource будет применяться для каждого экземпляра модели в вашей коллекции, а затем возвращен вам в качестве ответа JSON.

...