Laravel есть ли способ дехэшировать идентификаторы данных в URL-адресе перед доступом к маршруту?

Я использую пакет hashids\hashids для хеширования идентификатора данных, отправленных через URL-адрес (например, .../post/bsdfs/edit, «bsdfs» — это закодированное значение). Я следовал методу доступа Stuart Wagner. сделать это. Ниже показано, как я это делаю:

use Hashids\Hashids;

class Post extends Model {
    protected $appends = ['hashid'];

    public function getHashidAttribute() {
        $hashid = new Hashids(config('hash.keyword'));

        return $hashid->encode($this->attributes['id']);
    }
}

Перед хешированием идентификаторов я получаю post/2/edit. После процесса хэширования я получаю post/bsdfs/edit, что меня вполне устраивает.

Проблема возникает при перенаправлении на закодированный маршрут. Вот так выглядит мой маршрут:

use App\Http\Controllers\PostController;
    
Route::get('post/{post}/edit', 'PostController@edit')->name('post.edit');

После перенаправления получаю ошибку 404. Вот что принимает контроллер:

Use App\Models\Post;

class PostController extends Controller {
    //PS: I don't actually know what this method is called...
    public function edit(Post $post) {
        return view('post.edit')->with(compact('post'));
    }
}

Я знаю, что если я использую этот метод, Laravel ищет идентификатор «bsdfs», которого нет в базе данных. Что он должен сделать, так это декодировать хэш и получить идентификатор. Есть ли способ сделать это БЕЗ этого:

public function edit($id) {
    $hashid = new Hashids(config('hash.keyword'));
    $id= $hashid->decode($id);

    $post = Post::find($id);

    return view('post.edit')->with(compact('post'));
}

Как видите, моя цель здесь — уменьшить количество строк, сохраняя при этом идентификатор данных в кодируемом URL-адресе. Любая помощь будет оценена по достоинству. Спасибо.


person nazhannasir    schedule 19.04.2021    source источник


Ответы (1)


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

Итак, ваша модель должна иметь что-то вроде этого:

/**
 * Retrieve the model for a bound value.
 *
 * @param  mixed  $value
 * @param  string|null  $field
 * @return \Illuminate\Database\Eloquent\Model|null
 */
public function resolveRouteBinding($value, $field = null)
{
    $hashid = new Hashids(config('hash.keyword'));

    return $this->findOrFail($hashid->decode($value)[0]);
}

Таким образом, вы можете получить свой контроллер, как будто ничего не произошло:

public function edit(Post $post)
{
    return view('post.edit')->with(compact('post'));
}
person matiaslauriti    schedule 19.04.2021
comment
Возвращаемые данные представлены в виде массива. Это из-за хашидов\хашидов? - person nazhannasir; 19.04.2021
comment
Какая из всех трех возможных точек возвращается в виде массива? $hashid->decode($value), ` вернуть $this-›findOrFail(...)` или ` вернуть вид('post.edit')-›with(compact('post'));` ? Поделитесь здесь ошибкой, которая у вас возникла, пожалуйста... - person matiaslauriti; 19.04.2021
comment
Я dd($hashid-›decode($value));, он возвращает массив: 1 [[0] => 1].. Я не получил ошибку, но красноречивый пуст - person nazhannasir; 19.04.2021
comment
Я никогда не использовал библиотеку, которую вы используете, я видел документацию на github и вижу, что decode() всегда будет вернуть массив с 1 или более элементами. Так что смотрите мой обновленный ответ и попробуйте. - person matiaslauriti; 19.04.2021
comment
Я так понимаю, это ограничение самой библиотеки. Хорошо, большое спасибо за вашу помощь! Я отмечу это как правильный ответ. - person nazhannasir; 19.04.2021