Skip to content

Instantly share code, notes, and snippets.

@ericlbarnes
Created June 11, 2016 15:49
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save ericlbarnes/3b5d3c49482f2a190619699de660ee9f to your computer and use it in GitHub Desktop.
Save ericlbarnes/3b5d3c49482f2a190619699de660ee9f to your computer and use it in GitHub Desktop.
<?php
namespace App\Services;
use App\Post;
class Slug
{
/**
* @param $title
* @param int $id
* @return string
* @throws \Exception
*/
public function createSlug($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($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($slug, $id = 0)
{
return Post::select('slug')->where('slug', 'like', $slug.'%')
->where('id', '<>', $id)
->get();
}
}
@gentritabazi
Copy link

Usage:

use App\Helpers\CoolSlug;
$slugLibrary = new CoolSlug(\App\Post::class);
return $slugLibrary->createSlug('test');

CoolSlug Class:

<?php
namespace App\Helpers;

class CoolSlug {
    private $entity;

    /**
     * Instantiate a new CoolSlug instance.
     */
    public function __construct($entity) {
        $this->entity = $entity;
    }
    
    /**
     * Generate a URL friendly "slug" from the given string.
     * 
     * @param $title String
     * @return string
     * @throws \Exception
     */
    public function createSlug($title) {
        // Normalize the title
        $slug = \Illuminate\Support\Str::slug($title, '-');

        // Get any that could possibly be related.
        // This cuts the queries down by doing it once.
        $allSlugs = $this->getRelatedSlugs($slug);

        // If we haven't used it before then we are all good.
        if($allSlugs == 0) {
            return $slug;
        }

        // Just append numbers like a savage until we find not used.
        for($i = 1; $i <= 20; $i++) {
            $newSlug = $slug. '-'. $i;
            if($this->getRelatedSlugs($newSlug) == 0) {
                return $newSlug;
            }
        }

        throw new \Exception('Can not create a unique slug.');
    }

    protected function getRelatedSlugs($slug) {
        return call_user_func(array($this->entity, 'select'), 'permalink')->where('permalink', $slug)->count();
    }
}

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