Managing routes for multiple models using slugs without prefixes in Laravel.
In Laravel, managing routes for multiple models using slugs without prefixes can be achieved by following these steps:
- Define the URL slug in each model:
First, you need to define a slug
attribute in each model that will be used to generate the URL. This attribute should be defined as an accessor and a mutator. The accessor will be used to retrieve the slug value, while the mutator will be used to set the slug value based on the given input.
// app/Models/Post.php
class Post extends Model
{
// ...
public function getSlugAttribute()
{
return $this->title->slug;
}
public function setSlugAttribute($value)
{
$this->attributes['slug'] = $value;
$this->save();
}
}
// app/Models/Page.php
class Page extends Model
{
// ...
public function getSlugAttribute()
{
return $this->title->slug;
}
public function setSlugAttribute($value)
{
$this->attributes['slug'] = $value;
$this->save();
}
}
- Define the
slug
method in each model:
Next, you need to define a slug
method in each model that will be used to generate the slug value based on the given input. This method should convert the given input to a URL-friendly string and check if the slug already exists in the database.
// app/Models/Post.php
class Post extends Model
{
// ...
public function getSlugAttribute()
{
return $this->title->slug;
}
public function setSlugAttribute($value)
{
$this->attributes['slug'] = $value;
$this->save();
}
public function getSlugValueAttribute()
{
return $this->title->value;
}
public function setSlugValueAttribute($value)
{
$this->title->value = $value;
$this->title->save();
$this->save();
return $this->slug;
}
public function getSlugMethod()
{
return $this->isDirty('slug') ? $this->getSlugValueAttribute() : $this->slug;
}
public function getRouteKeyName()
{
return 'slug';
}
public function getSlug()
{
return $this->isDirty('slug') ? $this->getSlugValueAttribute() : $this->fresh()->slug;
}
public function getUrlAttribute()
{
return route('posts.show', $this->slug);
}
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
$this->title = Title::firstOrCreate([
'value' => Str::slug($value),
]);
$this->setSlugValueAttribute($this->title->fresh()->value);
}
public function setContentAttribute($value)
{
$this->attributes['content'] = $value;
}
public function setPublishedAtAttribute($value)
{
$this->attributes['published_at'] = $value;
$this->save();
}
public function setCreatedAtAttribute($value)
{
$this->attributes['created_at'] = $value;
}
public function setUpdatedAtAttribute($value)
{
$this->attributes['updated_at'] = $value;
}
public function title()
{
return $this->belongsTo(Title::class);
}
}
// app/Models/Page.php
class Page extends Model
{
// ...
public function getSlugAttribute()
{
return $this->title->slug;
}
public function setSlugAttribute($value)
{
$this->attributes['slug'] = $value;
$this->save();
}
public function getSlugValueAttribute()
{
return $this->title->value;
}
public function setSlugValueAttribute($value)
{
$this->title->value = $value;
$this->title->save();
$this->save();
return $this->slug;
}
public function getSlugMethod()
{
return $this->isDirty('slug') ? $this->getSlugValueAttribute() : $this->slug;
}
public function getRouteKeyName()
{
return 'slug';
}
public function getSlug()
{
return $this->isDirty('slug') ? $this->getSlugValueAttribute() : $this->fresh()->slug;
}
public function getUrlAttribute()
{
return route('pages.show', $this->slug);
}
public function setTitleAttribute($value)
{
$this->attributes['title'] = $value;
$this->title = Title::firstOrCreate([
'value' => Str::slug($value),
]);
$this->setSlugValueAttribute($this->title->fresh()->value);
}
public function setContentAttribute($value)
{
$this->attributes['content'] = $value;
}
public function setPublishedAtAttribute($value)
{
$this->attributes['published_at'] = $value;
$this->save();
}
public function setCreatedAtAttribute($value)
{
$this->attributes['created_at'] = $value;
}
public function setUpdatedAtAttribute($value)
{
$this->attributes['updated_at'] = $value;
}
public function title()
{
return $this->belongsTo(Title::class);
}
}
- Define the routes:
Finally, you need to define the routes for each model without prefixes. You can define the routes in the routes/web.php
file or in a separate route file.
// routes/web.php
Route::get('/{model}/{slug}', function ($model, $slug) {
$modelInstance = app()->make($model)->whereSlug($slug)->firstOrFail();
return view('models.'.$model.'.show', compact('modelInstance'));
})->where(['model' => ['Post', 'Page']]);
In this example, the {model}
wildcard will match either Post
or Page
, and the {slug}
wildcard will match the slug value for the corresponding model instance.
With these steps, you should be able to manage routes for multiple models using slugs without prefixes in Laravel.