Skip to content

Instantly share code, notes, and snippets.

@blood72
Last active October 29, 2020 18:42
Show Gist options
  • Save blood72/ce5f13863522b3d32721926bccf9a317 to your computer and use it in GitHub Desktop.
Save blood72/ce5f13863522b3d32721926bccf9a317 to your computer and use it in GitHub Desktop.
<?php
namespace App\Concerns;
use App\Casts\HashableKey;
trait CanRouteKeyHashing
{
/** @var bool */
protected $hashedKey = false;
/**
* Get the value of the model's route key.
*
* @return mixed
*/
public function getRouteKey()
{
if ($this->hashedKey) {
return hashids()->encodeHex(parent::getRouteKey());
}
return parent::getRouteKey();
}
/**
* 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)
{
if ($this->hashedKey) {
$value = hashids($value)->decodeHex();
}
return parent::resolveRouteBinding($value, $field);
}
/**
* Initialize the trait for an instance.
*
* @return void
*/
public function initializeCanRouteKeyHashing()
{
if (! isset($this->casts[$this->getKeyName()])) {
$this->casts[$this->getKeyName()] = HashableKey::class;
}
}
}
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Database\Eloquent\SerializesCastableAttributes;
class HashableKey implements CastsAttributes, SerializesCastableAttributes
{
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function get($model, $key, $value, $attributes)
{
return $value;
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function set($model, $key, $value, $attributes)
{
return $value;
}
/**
* Serialize the attribute when converting the model to an array.
*
* @param mixed $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function serialize($model, string $key, $value, array $attributes)
{
if (property_exists($model, 'hashedKey')) {
return $model->getRouteKey();
}
return $value;
}
}
<?php
namespace App\Packages;
/**
* @method \Hashids\Hashids|string encode(mixed ...$numbers)
* @method \Hashids\Hashids|array decode(string $hash = '')
* @method \Hashids\Hashids|string encodeHex(string $str = '')
* @method \Hashids\Hashids|string decodeHex(string $hash = '')
*/
class Hashids
{
/** @var \Vinkla\Hashids\HashidsManager */
protected $hashids;
/** @var mixed */
protected $data;
/**
* Hashids constructor.
*
* @param $data
*/
public function __construct($data = null)
{
$this->hashids = app(\Vinkla\Hashids\HashidsManager::class);
$this->data = $data;
}
/**
* @param $methods
* @param $parameters
* @return mixed
*/
public function __call($methods, $parameters)
{
return $this->hashids->$methods($this->data ?? $parameters);
}
/**
* @return string
*/
public function __toString()
{
return (string) $this->encode($this->data);
}
}
<?php
if (! function_exists('hashids')) {
/**
* @param mixed $parameter
* @return \Vinkla\Hashids\HashidsManager|App\Packages\Hashids
*/
function hashids($parameter = null)
{
if (is_null($parameter)) {
return app(\Vinkla\Hashids\HashidsManager::class);
}
return new \App\Packages\Hashids($parameter);
}
}
@blood72
Copy link
Author

blood72 commented May 10, 2020

Usage

base

hashids() // return \Vinkla\Hashids\HashidsManager

hashids('9xABBQAv') // return \App\Packages\Hashids

encode - same result: '9xABBQAv'

hashids(1234)->encode();
hashids()->encode(1234);
$hashids = hashids(1234);

"$hashids";

decode - same result: [1234]

hashids('9xABBQAv')->decode();
hashids()->decode('9xABBQAv');

model routing

namespace App\Models;

use App\Traits\CanRouteKeyHashing;
use Illuminate\Database\Eloquent\Model;

class Example extends Model
{
    use CanRouteKeyHashing;

    protected $hashedKey = true;
}

explicit binding (if you want)

// in app/Providers/RouteServiceProvider.php

// ...

public function boot()
{
    parent::boot();

    Route::model('example', \App\Models\Example::class, function ($hash) {
        $id = hashids()->decodeHex($hash);

        return Example::findOrFail($id);
    });
}

// ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment