-
app/Helpers/HasSlug.php
Open in GitHub// There's a mismatch with the folder name of "Helpers", but these are not global helpers, they are Traits namespace App\Helpers; trait HasSlug { public function slug(): string { return $this->slug; } public function setSlugAttribute(string $slug) { $this->attributes['slug'] = $this->generateUniqueSlug($slug); } public static function findBySlug(string $slug): self { return static::where('slug', $slug)->firstOrFail(); } private function generateUniqueSlug(string $value): string { $slug = $originalSlug = Str::slug($value) ?: Str::random(5); $counter = 0; while ($this->slugExists($slug, $this->exists ? $this->id() : null)) { $counter++; $slug = $originalSlug.'-'.$counter; } return $slug; } private function slugExists(string $slug, int $ignoreId = null): bool { $query = $this->where('slug', $slug); if ($ignoreId) { $query->where('id', '!=', $ignoreId); } return $query->exists(); } }
-
app/Models/Tag.php
Open in GitHubuse App\Helpers\HasSlug; final class Tag extends Model { use HasSlug; // ... other Model code }
-
app/Models/Article.php
Open in GitHubuse App\Helpers\HasSlug; final class Article extends Model { use HasSlug; // ... other Model code }
-
routes/bindings.php
Open in GitHub// This file overrides the default Laravel Route Model Binding with other rules // including findBySlug() that comes from the HasSlug Trait Route::bind('tag', function (string $slug) { return App\Models\Tag::findBySlug($slug); }); Route::bind('article', function (string $slug) { return App\Models\Article::findBySlug($slug); });