Laravel Slugs with Str::slug
Asked Answered
K

6

10

Looking at Str::slug for my frontend URL generation but just wondering how you guys go about implementing it with routes etc, for example, how would you guys go about changing http://www.example.com/courses/1 to http://www.example.com/courses/this-course

Kalimantan answered 1/7, 2013 at 9:7 Comment(0)
K
12

OK, I did it this way:

// I have a slug field in my courses table and a slug field in my categories table, along with a category_id field in my courses table.

// Route 

Route::get('courses/{categorySlug}/{slug?}', function($categorySlug, $slug) {
    $course = Course::leftJoin('categories', 'categories.id', 'courses.category_id')
        ->where('categories.slug', $categorySlug)
        ->where('courses.slug', $slug)
        ->firstOrFail();

    return View::make('courses.show')->with('course', $course);
});

Works like a charm. It gets the $categorySlug and $slug variables then uses them to filter the Eloquent model Course to get the correct course object from the database.

EDIT: You can generate a URL in your view like:

http://www.example.com/courses/it-training/mcse

By doing something like:

<a href="{{ URL::to('courses/'.$course->category->parentCategorySlug($course->category->parent_id).'/'.$course->category->slug.'/'. $course->slug) }}" title="{{ $course->title }}">{{ $course->title }}</a>

A have a method in my Category like below that retrieves the parent category slug. This could be better achieved though using some sort of presenter class which would allow you to simply use $course->url but I haven't got around to doing this yet. I will update the answer when I do.

public function parentCategorySlug($parentId)
{
    if ($parentId === '0')
    {
        return $this->slug;
    }

    return $this->where('id', $parentId)->first()->slug;
}
Kalimantan answered 1/7, 2013 at 11:48 Comment(0)
S
5

You can use the cvierbrock's Eloquent-Sluggable package.

Saville answered 11/2, 2014 at 14:0 Comment(0)
F
4

As for me I created a helper function and used the following method taken from here.

 public static function getSlug($title, $model) {
    $slug = Str::slug($title);
    $slugCount = count( $model->whereRaw("url REGEXP '^{$slug}(-[0-9]*)?$'")->get() );
    return ($slugCount > 0) ? "{$slug}-{$slugCount}" : $slug;
}
Footstep answered 18/5, 2014 at 19:16 Comment(0)
A
2

You can create a related model Slug, and approach the course in your methods like so:

$course = Slug::where('slug', $slug) -> firstOrFail() -> course;
Apia answered 22/4, 2015 at 6:43 Comment(0)
M
1

I have also implemented a similar URL mapping but I preferred to have both the ID and the slug in the requested URL, like this:

http://www.example.com/courses/1/my-laravel-course

This method allows me to get the requested course object from the ID given in the URL, rather than having to store the slugs in my DB table.

Route::post('courses/(:num)/(:any)', function ($courseid, $slug) {
    $course = Course::where('id', '=', $courseid)->get();
    return View::make('courses.show')->with('course', $course);
}
Manymanya answered 2/7, 2013 at 11:2 Comment(2)
how do I get this url in the controller to display it?Saville
The urls should be unique, in this case you will get the same for /1/my-laravel-course and /1/lorem-ipsum for exampleBrassard
B
0

For Laravel 8:

Given my URL:

http://www.example.com/courses/this-course

My route:

Route::get('/courses/{course:slug}' , function(Course $course){
     return view('showCourse' , [
         'course' => $course
     ])
})
Bradlybradman answered 15/8, 2022 at 20:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.