Skip to content

Instantly share code, notes, and snippets.

@ruaq
Forked from TheNodi/HashidsRoutable.php
Last active December 11, 2018 00:12
Show Gist options
  • Save ruaq/9fdca139659d60ad56c833495b19098a to your computer and use it in GitHub Desktop.
Save ruaq/9fdca139659d60ad56c833495b19098a to your computer and use it in GitHub Desktop.
Laravel Model Bindings with Hashids
<?php
namespace App;
use Vinkla\Hashids\HashidsManager;
/**
* Bind a model to a route based on the hash of
* its id (or other specified key).
*
* @package App
*
* @mixin \Illuminate\Database\Eloquent\Model
*/
trait HashidsRoutable
{
/**
* Instantiate appropriate Hashids connection
*
* @return \Hashids\Hashids
*/
protected function getHashidsInstance()
{
return app(HashidsManager::class)->connection($this->getHashidsConnection());
}
/**
* Determine Hashids connection to use
*
* @return null|string
*/
protected function getHashidsConnection()
{
return null;
}
/**
* Encode a parameter
*
* @param int $parameter
* @return string
*/
protected function encodeParameter($parameter)
{
return $this->getHashidsInstance()->encode($parameter);
}
/**
* Decode parameter
*
* @param string $parameter
* @return null|int Decoded value or null on failure
*/
protected function decodeParameter($parameter)
{
if (count($decoded = $this->getHashidsInstance()->decode($parameter)) != 1) {
// We are expecting a single value from the decode parameter,
// if none or multiple are returned we just fail
return null;
}
return $decoded[0];
}
/**
* Instruct implicit route binding to use
* our custom hashed parameter.
*
* This is long and crazy to avoid parameters
* collisions.
*
* @return string
*/
public function getRouteKeyName()
{
return 'hashidsRoutableHashParam';
}
/**
* Determine which attribute to encode
*
* @return string
*/
public function getRouteHashKeyName()
{
return $this->getKeyName();
}
/**
* Get beginning value
*
* @return string
*/
public function getRouteHashKey()
{
return $this->getAttribute($this->getRouteHashKeyName());
}
/**
* Encode real parameter to url value for bindings
*
* @return string
*/
public function getHashidsRoutableHashParamAttribute()
{
return $this->encodeParameter($this->getRouteHashKey());
}
}

HashIds Routable Models

Turns a model binding from /profile/1 to /profile/XDBoYzYE just by using a trait.

Installation

This trait is based on laravel-hashids, require it first using composer. Then just copy paste the trait below somewhere in your laravel project. After that, copy the following code to RouteServiceProvider in the public function boot.

RouteServiceProvider.php

Route::bind('id', function ($id) {
            return \Hashids::decode($id)[0] ?? $id;
        });

Usage

Basic Usage

To use the encoded version of model's id just use the trait like:

<?php
// ...
class User extends Authenticatable
{
    use HashidsRoutable;
    // ....
}

Custom Attribute

To use another attribute rather then id override the getRouteHashKeyName() method:

<?php
// ...
class User extends Authenticatable
{
    use HashidsRoutable;
    
    public function getRouteHashKeyName()
    {
        return 'another_attribute_name';
    }
    // ....
}

Custom connection

By default the trait will use laravel-hashids's default connection, to change it on a per-model base override the getHashidsConnection() method:

<?php
// ...
class User extends Authenticatable
{
    use HashidsRoutable;
    
    public function getHashidsConnection()
    {
        return 'alternative';
    }
    // ....
}

Without laravel-hashids

If you don't want to use laravel-hashids (Why shouldn't you?), change the getHashidsInstance() method to return a new instance of hashids.php:

<?php
// ...
trait HashidsRoutable
{
    protected function getHashidsInstance()
    {
        return new Hashids\Hashids('your-salt', 0, 'abcdefghijklmnopqrstuvwxyz');
    }
    
    // ...

Disclaminer

Overriding the where() method of the Model class might be consider dirty. Removed the where() method and added Route::bind. (quick&dirty -> sry ;)

If you don't like it, use Explicit Binding instead of this trait to build your urls.

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