Skip to content

Instantly share code, notes, and snippets.

@shibbirweb
Created May 27, 2019 18:12
Show Gist options
  • Save shibbirweb/84f0ab7c9f74fe02e8347531557b645b to your computer and use it in GitHub Desktop.
Save shibbirweb/84f0ab7c9f74fe02e8347531557b645b to your computer and use it in GitHub Desktop.
Generate unique slug for laravel
<?php
namespace App\Helpers;
use App\Post;
/**
* Unique slug generator
* Created by Shibbir Ahmed
* Source: https://gist.github.com/ericlbarnes/3b5d3c49482f2a190619699de660ee9f
*
* @package \App\Helpers
*/
class Slug
{
private $table_model;
private $table_column;
public static function instance($table_model = Post::class, $column_name = 'slug')
{
return new Slug($table_model, $column_name);
}
/**
* @param $title
* @param int $id
* @return string
* @throws \Exception
*/
function __construct($entity = Post::class, $slugAttr = 'slug')
{
$this->table_model = $entity;
$this->table_column = $slugAttr;
}
/**
* @param $title
* @param int $id
* @return string
* @throws \Exception
*/
public function createSlug($title, $id = 0)
{
//if empty title throw an exception
if (empty($title)) {
throw new \Exception('Title is empty');
}
// Normalize the title
//check title contains unicode character
if (strlen($title) != strlen(utf8_decode($title))) {
$slug = preg_replace("#(\p{P}|\p{C}|\p{S}|\p{Z})+#u", "-", $title);
}else {
$slug = str_slug($title);
}
// Get any that could possibly be related.
// This cuts the queries down by doing it once.
$allSlugs = $this->getRelatedSlugs($slug, $id);
// If we haven't used it before then we are all good.
if (!$allSlugs->contains($this->table_column, $slug)) {
return $slug;
}
// Just append numbers like a savage until we find not used.
// It will try 10000 times
for ($i = 1; $i <= 1000; $i++) {
$newSlug = $slug . '-' . $i;
if (!$allSlugs->contains($this->table_column, $newSlug)) {
return $newSlug;
}
}
throw new \Exception('Can not create a unique slug');
}
//find the related slug
protected function getRelatedSlugs($slug, $id = 0)
{
return call_user_func(array($this->table_model, 'select'), $this->table_column)->where($this->table_column, 'like', $slug . '%')
->where('id', '<>', $id)
->get();
}
}
<?php
use Illuminate\Http\Request;
use App\Helpers\Slug;
use App\Post;
public function store(Request $request)
{
//Create slug
$post->slug = Slug::instance(Post::class, 'slug')->createSlug($request->title); // circular slug
}
public function update(Request $request, $id)
{
//Update slug
$post->slug = Slug::instance(Post::class, 'slug')->createSlug($request->title, $id); // circular slug
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment