Skip to content

Instantly share code, notes, and snippets.

@codyphobe
Forked from TheNodi/HashidsRoutable.php
Created May 7, 2017 16:51
Show Gist options
  • Save codyphobe/f7179a21ca7f05ea655230c0219b9bec to your computer and use it in GitHub Desktop.
Save codyphobe/f7179a21ca7f05ea655230c0219b9bec 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 string $parameter
* @return string
*/
protected function encodeParameter($parameter)
{
return $this->getHashidsInstance()->encode($parameter);
}
/**
* Decode parameter
*
* @param string $parameter
* @return array
*/
protected function decodeParameter($parameter)
{
return $this->getHashidsInstance()->decode($parameter);
}
/**
* 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());
}
/**
* Transform a checking by hashed key to real query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function where()
{
$params = func_get_args();
if ($params[0] == $this->getRouteKeyName()) {
return parent::where($this->getRouteHashKeyName(), $this->decodeParameter($params[1]));
}
return parent::where(...$params);
}
}

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.

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'y 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. 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