Skip to content

Instantly share code, notes, and snippets.

@alexrusin
Created May 24, 2019 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexrusin/c107f34e274ae1be4ec8028d2ff7af49 to your computer and use it in GitHub Desktop.
Save alexrusin/c107f34e274ae1be4ec8028d2ff7af49 to your computer and use it in GitHub Desktop.
Bootable Sluggable Trait
// https://dotdev.co/creating-unique-title-slugs-with-laravel/
// https://andy-carter.com/blog/using-laravel-s-eloquent-traits
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait Sluggable
{
public static function bootSluggable()
{
static::saving(function ($model) {
$model->slug = $model->createSlug(get_class($model), $model->title);
});
static::updating(function ($model) {
$model->slug = $model->createSlug(get_class($model), $model->title, $model->id);
});
}
/**
* @param $title
* @param int $id
* @return string
* @throws \Exception
*/
public function createSlug($className, $title, $id = 0)
{
// Normalize the title
$slug = Str::slug($title);
// Get any that could possibly be related.
// This cuts the queries down by doing it once.
$allSlugs = $this->getRelatedSlugs($className, $slug, $id);
// If we haven't used it before then we are all good.
if (!$allSlugs->contains('slug', $slug)) {
return $slug;
}
// Just append numbers like a savage until we find not used.
for ($i = 1; $i <= 10; $i++) {
$newSlug = $slug . '-' . $i;
if (!$allSlugs->contains('slug', $newSlug)) {
return $newSlug;
}
}
throw new \Exception('Can not create a unique slug');
}
protected function getRelatedSlugs($className, $slug, $id = 0)
{
return $className::select('slug')->where('slug', 'like', $slug . '%')
->where('id', '<>', $id)
->get();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment