DEV Community

Cover image for Generate Slug Keyword from Title: Laravel + AJAX
ysfjr1
ysfjr1

Posted on

Generate Slug Keyword from Title: Laravel + AJAX

If you work with project or blog where records require so-called slug (posts, pages etc.), it’s convenient to generate slug immediately after title has been typed in. This article will show you how to do it in Laravel, with AJAX and with a help of one Laravel package.

First, what we’re doing here. This is the example:

We have a form to add a page, and our goal is to have Slug field auto-generated, as we finish typing in the Title.

Not only that, slug should be unique for every post, even if title is the same.

Step 1. Blade Create Form

I will show you, how resources/views/admin/pages/create.blade.php looks like. To be exact, the part responsible for those two fields – title and slug:

<div class="form-group">
    <label for="title">Title*</label>
    <input type="text" id="title" name="title" class="form-control">
</div>
<div class="form-group">
    <label for="slug">Slug*</label>
    <input type="text" id="slug" name="slug" class="form-control">
</div>
Enter fullscreen mode Exit fullscreen mode

So, the code is simple, nothing to comment here. Now, let’s add some JavaScript, that is fired when title value is changed.

Step 2. AJAX Call On Title Change

In the “main” Blade layout file, I have a special @yield(‘scripts’) code that allows to add any JavaScript to any other Blade template. So, that’s exactly what we will do – add this code to the bottom of our pages/create.blade.php:

@section('scripts')
<script>
  $('#title').change(function(e) {
    $.get('{{ route('pages.check_slug') }}', 
      { 'title': $(this).val() }, 
      function( data ) {
        $('#slug').val(data.slug);
      }
    );
  });
</script>
@endsection
Enter fullscreen mode Exit fullscreen mode

Now, we need to create the logic behind pages.check_slug route.

Step 3. Route/Controller to Return Slug

First, in routes/web.php we add this line:

Route::get('pages/check_slug', 'PagesController@check_slug')
  ->name('pages.check_slug');
Enter fullscreen mode Exit fullscreen mode

Next, we create app/Http/Controllers/PagesController method check_slug(). We’ll start from a simple version using Laravel’s str_slug() helper.

public function check_slug(Request $request)
{
    $slug = str_slug($request->title);
    return response()->json(['slug' => $slug]);
}
Enter fullscreen mode Exit fullscreen mode

Simple, right? We make a slug and return it. That could be the end of our tutorial, but we forgot one important rule – slugs should be unique. How to check it?

Step 4. Making Slug Unique

Not only that, we need to not only check uniqueness, but also automatically add -1, -2, -3 and other numbers to the end of the slug, to generate a new unique one.

For that, I’ve decided to not reinvent the wheel and to use an existing package eloquent-sluggable. It’s not the only slug-related package on the market, but it has a very useful (in our case) feature of generating slug without saving it to the database.

We install the package with this command:

composer require cviebrock/eloquent-sluggable
Enter fullscreen mode Exit fullscreen mode

Next, we need to prepare our Model app/Page.php to make it “sluggable”:

use Cviebrock\EloquentSluggable\Sluggable;

class Page extends Model
{
    use Sluggable;

    /**
     * Return the sluggable configuration array for this model.
     *
     * @return array
     */
    public function sluggable()
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

We’ve created a method that defines to generate slug field from title field of pages database table.

And now, final step, we can replace old “simple” method of generating slug in PagesController:

use Cviebrock\EloquentSluggable\Services\SlugService;

public function check_slug(Request $request)
{
    // Old version: without uniqueness
    $slug = str_slug($request->title);

    // New version: to generate unique slugs
    $slug = SlugService::createSlug(Page::class, 'slug', $request->title);

    return response()->json(['slug' => $slug]);
}
Enter fullscreen mode Exit fullscreen mode

And, that’s it!

Top comments (0)