Creating Sluggable URLs Using the Laravel Framework

Routing

Committed to the LaraBrain by: wjgilmore (@wjgilmore) at October 14, 2015 11:04 pm

Creating user- and SEO-friendly URLs is easy thanks to the eloquent-sluggable package.

Thanks to Laravel's RESTful (also known as resourceful) controller support, it's fairly trivial to build interfaces for creating, retrieving, updating, and deleting data. These RESTful interfaces depend upon a well-defined URL structure, and the show action (displaying information about a specific record) in particular requires that a record's primary key be passed along as part of the URL, such as:

http://larabrain.com/tips/3 

The 3 identifies a particular record by its primary key, which can then be retrieved in the controller's show action like so:

$tip = Tip::findOrFail(3);

However, these URLs aren't particularly eye-appealing. I'd rather employ URLs that look like this:

http://larabrain.com/tips/debugging-output-with-laravel-debugbar

These user- and SEO-friendly URLs can be integrated easier than you think, thanks to the eloquent-sluggable package. To install this package you'll need to require the package via Composer:

$ composer require cviebrock/eloquent-sluggable

Next, update your project's config/app.php file to reference the service provider:

'providers' => [
    ...
    'Cviebrock\EloquentSluggable\SluggableServiceProvider',
    ...
];

Next, you'll need to make your model(s) sluggable. This is accomplished by adding a column to the associated table which will store the slug (e.g. debugging-output-with-laravel-debugbar). For instance, to add a column named slug to the tips table you can run the following command:

$ php artisan sluggable:table tips

With the slug column in place, all that remains is to update the sluggable model, referencing the Sluggable interface and trait, and then identifying the name of the field you'll use to automatically create the slug:

<?php

...

use Cviebrock\EloquentSluggable\SluggableInterface;
use Cviebrock\EloquentSluggable\SluggableTrait;

...

class Tip extends Model implements SluggableInterface
{

    use SluggableTrait;

    protected $sluggable = [
        'build_from' => 'name',
        'save_to'    => 'slug'
    ];

    ...

}

Once the model changes are saved, anytime a record is created or modified, the name field value will be used to modify the associated slug field. Therefore a tip named "Debugging output with Laravel Debugbar" will have a corresponding slug named debugging-output-with-laravel-debugbar.

Another great feature of this package is the availability of a custom finder which allows you to find a record according to its slug or its ID:

$tip = Tip::findBySlugOrIdOrFail($id);