Laravel Tutorials - How to Create Slugs in Laravel

How to Create Slugs in Laravel

/ 2019-10-02 Lukas Markevičius How to Create Slugs in Laravel featured image
Today we are going to learn how to create slugs in Laravel. You are going to learn:
  • Why use slugs
  • How to create slugs
  • How to show objects with the slugs
  • How to edit slugs

Why use Slugs

If you are familiar with Laravel framework you probably know how to make a basic model with CRUD. To view a single object from a database you usually call route with a controller function show. For Laravel to know which object to show you usually have to pass its id through route. For example, if you have a Post model and if you want to view a single post, you should call route like this {{ route('post.index', $post->id) }} and the URL would be something like this: https://example.com/post/2. This is the basic way to find a post from a database and return it to the user. However, it's not the prettiest method. What I mean is for the user it would be much nicer to see a URL like this: https://example.com/post/my-first-post. That part after post/ is called slug. It can identify the object you are trying to see just like the id could. This method also would benefit you if you are looking to improve your SEO and rank higher on Google. When search engines are indexing your pages they are also analyzing your URLs which help them to identify what this page is all about. So, today we are going to learn how to create slugs in Laravel.

How to Create Slugs

Let's just say that you already have a basic model and CRUD set up. For this example, we will use a Post model which have id, title, description and timestamps columns. What we will need next is to add an additional column named slug. We can do that by creating a new migration in your terminal:
$ php artisan make:migration add_slug_column_to_posts --table=posts

Now we can find a new migration file in database/migrations and create a new column:

<?php

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

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

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('slug');
});
}
}
After we save file we can then migrate it to the database by running a commandphp artisan migrate in terminal. If you are getting any errors it is probably because you have already some post data in a database which gives you an error of a duplicate entry. If that is the case you can delete all post from the database and migrate then. We can now add a new input field intopost.create view.
<form method="POST" action="{{ route('post.store') }}">

<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" value="{{ old('title') }}" placeholder="Post title">
</div>

<div class="form-group">
<label for="slug">Slug</label>
<input type="text" name="slug" class="form-control" value="{{ old('slug') }}" placeholder="post-slug">
</div>

<div class="form-group">
<label for="description">Description</label>
<textarea name="description" rows="8" cols="80" class="form-control">{{ old('description') }}</textarea>
</div>

<button type="submit" class="btn btn-primary">Create Post</button>
</form>

Now we need to update store function which in my example can be found in app/Http/Controllers/PostController.php:

public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|min:3|max:255',
'slug' => 'required|min:3|max:255|unique:posts',
'description' => 'required|min:3'
]);

$post = new Post;

$post->title = $request->title;
$post->slug = Str::slug($request->slug, '-');
$post->description = $request->description;

$post->save();

return redirect()->route('index');
}

We added a slug field to validate which also checks if a slug is unique or not. We used a method Str::slug()  to format string to slug. Don't forget to include use Illuminate\Support\Str;  at the top of the controller file. It basically changes any whitespace in to "-". Now we can try to create a new post. If everything ran smoothly you should now be able to create a post with a slug.

How to show Objects with the Slugs

Now we need to change routes for show function to find a post with a slug. We start by changing the URL which points to a post.show view.

<div class="row">
@foreach($posts as $post)
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h3>{{ $post->title }}</h3>
</div>
<div class="card-body">
<p>{{ substr($post->description, 0, 100) }}</p>
<a href="{{ route('post.show', $post->slug) }}" class="btn btn-primary btn-block">Read More</a>
</div>
</div>
</div>
@endforeach
</div>

Now we need to change route which will pass slug instead of an id in the routes/web.php:

Route::get('/post/{slug}', 'PostController@show')->name('post.show');

We changed /post/{id} in to /post/{slug}. Now we can change functionshow in our controller to find a post by the slug.

public function show($slug)
{
$post = Post::where('slug', $slug)->first();

return view('post.show')->withPost($post);
}

And now we can click on a post and it will redirect us to the post.show view with our newly created slug!

How to edit Slugs

If you want to be able to edit that slug we can change things just like before. Now we will change the URL of the Edit Post button:

<a href="{{ route('post.edit', $post->slug) }}" class="btn btn-primary">Edit Post</a>

And change the edit and update route in the routes/web.php file:

Route::get('/post/{slug}/edit', 'PostController@edit')->name('post.edit');
Route::post('/post/{slug}/edit', 'PostController@update')->name('post.update');

Now we can change functions in the PostController.php file:

public function edit($slug)
{
$post = Post::where('slug', $slug)->first();

return view('post.edit')->withPost($post);
}

And for the update function:

public function update(Request $request, $slug)
{
$this->validate($request, [
'title' => 'required|min:3|max:255',
'slug' => 'required|min:3|max:255|unique:posts,id,' . $slug,
'description' => 'required|min:3'
]);

$post = Post::where('slug', $slug)->first();

$post->title = $request->title;
$post->slug = Str::slug($request->slug, '-');
$post->description = $request->description;

$post->save();

return redirect()->route('post.show', $post->slug);
}

You can notice that we added new parameters to the validation unique rule. It is because when we wouldn't change our slug it would throw an error because we submitted the same slug. So we add additional parameters which check if the slug is unique except for the submitted slug itself if that makes any sense to you. Now, all we have to do is to add additional input field in the post.edit view:

<form method="POST" action="{{ route('post.update', $post->slug) }}">

<div class="form-group">
<label for="title">Title</label>
<input type="text" name="title" class="form-control" value="{{ $post->title }}">
</div>

<div class="form-group">
<label for="slug">Slug</label>
<input type="text" name="slug" class="form-control" value="{{ $post->slug }}">
</div>

<div class="form-group">
<label for="description">Description</label>
<textarea name="description" rows="8" cols="80" class="form-control">{{ $post->description }}</textarea>
</div>

<button type="submit" class="btn btn-primary">Update Post</button>
</form>

And that's it! You now have learned how to create slugs in Laravel.

How to Create Slugs in Laravel pinterest image

Related Tutorials

How to Generate a Simple XML Sitemap using Laravel

Posted 2019-08-13 Lukas Markevičius

Today we are going to learn how to generate a simple XML sitemap using Laravel. Mainly you can create it either manually or create some sort of automatic solution. To create it manually you can make y...

How to create Step by Step Laravel Project

Posted 2019-08-13 Lukas Markevičius

If you are a beginner and want to learn how to start developing Laravel applications you came to the right place because today we are going to learn step-by-step how to create your first Laravel 5.6 p...

Back