How to Generate Unique Slug in Laravel 8

How to Generate Unique Slug in Laravel 8

Admin
Admin・ 11 September 2021
10 min read ・ 14519 views

Laravel Unique Slug - In this article I will share a tutorial on how to generate slug in laravel 8 using the Str::slug helper and a tutorial on how to generate unique slug using the eloquent sluggable package.

What is Slug ?

Slug is a part of a URL that identifies a particular (unique) web page. An example of a slug is URL https://codelapan.com/post-slug, and means the slug of that URL is "post-slug". For SEO, include keywords in the URL and create a user-friendly URL.

Generate Slug in Laravel 8

To create slugs in laravel, we can actually use the helper provided by laravel, namely Str::slug. An example of its implementation is as below.

 public function store(Request $request)
    {
        $post            = new Post();
        $post->title  = $request->title;
        $post->slug = \Str::slug($request->title);
        $post->save();
    }

With the code above, $post->slug will take the value of $request->title and convert it into a user friendly URL. If the value of $request->title is the same as "How to Generate Unique Slug in Laravel 8" then the value of $post->slug will be the same as "how-to-generate-unique-slug-in-laravel-8". But if the slug is of type unique, when we add more data with the title "How to Generate Unique Slug in Laravel 8", the output will be error: "Integrity constraint violation: 1062 Duplicate entry 'how-to-generate-unique-slug-in-laravel -8' for key 'posts_slug_unique'".

How do we do that when we add the same title, it will automatically generate unique slug?

Okay, in this article, I will share how to create or generate unique slug in laravel 8. We can easily make something like that with the eloquent sluggable package. For how to apply it in laravel 8, the step by step will be explained below.


Generate Unique Slug in Laravel 8

In this tutorial how to generate unique slug in laravel 8, I will try to share step by step starting from installing the latest version of laravel, creating post model and migration file, installing package, setup database, setup view and defining routes.

Install Laravel

//via Laravel Installer
composer global require laravel/installer
laravel new laravel-unique-slug

//via Composer
composer create-project laravel/laravel laravel-unique-slug

In this first step, we need to install the latest version of laravel (currently version 8) which we will try to implement generate unique slug in laravel 8. To install laravel you can use the laravel installer or use composer like the example above.

Choose one method you want to use for laravel installation. From the two examples of laravel installation commands above, they will both generate a laravel project with the name laravel-unique-slug.

Wait until the installation process is complete and when it's finished, don't forget to enter the project directory using the cd laravel-uniqe-slug command.

Create Post Model & Migration

php artisan make:model Post -m

The second step, we will create the Post Model & Migration file. Run the command as above in the terminal. From the command will generate two files, namely;

app/Model/Post.php

database/migrations/[timestamp] _create_posts_table.php

Then open the [timestamp] _create_posts_table.php file that we just created and edit the code in the file to be as below.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug')->unique();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
} 

Setup Database

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_unique_slug
DB_USERNAME=root
DB_PASSWORD=

Having finished creating the Post Modal & Migration file, now we need to create a new database. Create a new database and don't forget to adjust the DB_DATABASE in the .env file to the same value as the database name that was created.

Then to run all migration files, run the command php artisan migrate.

Install Eloquent Slugable Package

composer require cviebrock/eloquent-sluggable

Update Post Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;

class Post extends Model
{
    use HasFactory;
    use Sluggable;

    protected $guarded = [];
    
    public function sluggable(): array
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }
}

Edit the Post.php model file by adding the sluggable trait and need to define the abstact method sluggable() like the code sample above.

Setup View

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">

    <title>Generate Unique Slug in Laravel 8</title>
  </head>
  <body>
    <div class="container mt-5">
        <div class="row">
            <h1 class="text-center my-3">
                Generate Unique Slug in Laravel 8
            </h1>
            <form action="/" method="POST">
                @csrf
            <div class="mb-3">
                <label for="title" class="form-label">Title</label>
                <input type="text" name="title" class="form-control" id="title">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
            </form>
        </div>
    </div>

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>

  </body>
</html>

Edit the welcome.blade.php file in the resources/views directory to be like the code above. The code above is a starter template from bootstrap 5 with the addition of a form with input fields for title and post actions.

Setup Route

Route::post('/', function () {
    App\Models\Post::create(['title' => request('title')]);
    return redirect()->back();  
});

In the routes/web.php, we just need to define or create a new route as above. That way, when we input the title and click submit, the title data will be added to the posts table in the database and will automatically generate unique slugs.

Eloquest Sluggable Testing

Okay, after going through step by step how to generate unique slug in laravel 8 starting with installing laravel, creating post model & migration, database setup, installing sluggable package, setup view to setup route, and now it's time to test whether our simple project is has successfully generated unique slug or not.

Please run the laravel project server with the php artisan serve command, then open the laravel project in the browser. Try several times inputting the same title data.

output: laravel unique slug

And if we check the database, the result is that when we input the same title several times, the eloquent-sluggable package will automatically add an increment counter at the end of the slug as shown above.

Display Realtime Laravel Unique Slug

show realtime laravel unique slug

How to display the unique slug that has been generated using the eloquent sluggable package in realtime? We can create or display a unique slug that has been generated as shown above using additional jQuery. How to make it will be explained below.

Edit Blade

<div class="mb-3">
    <label for="slug" class="form-label">Slug</label>
    <input type="text" name="slug" class="form-control" id="slug">
</div>

The first step, open the welcome.blade.php file and add a new input field code like the code above to display the generated slug and place the above code just below the input field title.

{{-- jQuery Script --}}
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
{{-- Check Slug --}}
<script>
    $('#title').change(function(e) {
       $.get('{{ url('check_slug') }}', 
       { 'title': $(this).val() }, 
       function( data ) {
           $('#slug').val(data.slug);
       }
       );
    });
</script>

Then add jquery and script to check slugs and display them in input fields (in view). In the script, we point the url to check_slug and display the slug data that has been generated into the input field with the id="slug".

Update Route

use Cviebrock\EloquentSluggable\Services\SlugService;
....
....
....
....
Route::get('check_slug', function () {
    $slug = SlugService::createSlug(App\Models\Post::class, 'slug', request('title'));
    return response()->json(['slug' => $slug]);
});

Next, open the routes/web.php file and add the route code as above and don't forget to use trait use Cviebrock\EloquentSluggable\Services\SlugService;.

That way, now if we open our Laravel project in the browser, there is already an additional new input field for the slug and if we enter a new title data in the title input field, the slug input field will automatically display the slug that has been generated in realtime using eloquent sluggable package.

Good luck. Hopefully this article can help and see you in the next article. 😊 🚀 🚀

 

Full Documentation: Eloquent Sluggable Package

 

Credit: Online illustrations by Storyset

Tinggalkan Komentar
Loading Comments