Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

henryoladj's avatar

Unique Slug Duplicate Entry

On my website i have a slug which is unique, but once users try to post same news it shows this error Integrity constraint violation: 1062 Duplicate entry.

Please how can i resolve this by saying post already made or by adding the slug url with an id of the news at the back i.e localhost:8000/post/welcome-to-my-post-1 if the ID of the post is 1

Thanks

0 likes
22 replies
lightyagami's avatar

the slug is unique but you would make a post id to it, so, everytime someone make a new post, only the id is different, also, i think is very easy someone make a slug equal to other post

siangboon's avatar

by adding the slug url with an id of the news at the back i.e localhost:8000/post/welcome-to-my-post-1 if the ID of the post is 1

this should be pretty straight forward, if you can store post's slug as 'welcome-to-my-post' you should be able store post 'welcome-to-my-post-1', please try it out yourself.

henryoladj's avatar

I did this $news->slug = Str::slug($news->subject->'{id}');

and it is giving me error

Snapey's avatar

Thats because it makes no sense.

try

$news->slug = Str::slug($news->subject) . '-' .  $news->id;

But remember you can only do this once you have already created the model (and got its id), so you will need to set slug as nullable in your migration for the model

henryoladj's avatar

Model News.php

protected static function boot() {
    parent::boot();

    static::creating(function ($news, $slug=null) {
        $news->slug = Str::slug($news->subject).'-'.$news->id;
        
    });
    }

It is still saying duplicate entry after doing this

Snapey's avatar

You cannot do it in creating because the model ID still has not been created by the database.

Move it to created and add save();

It does mean that you will have two database writes for every post

henryoladj's avatar

@snapey

 protected static function boot() {
    parent::boot();

    static::creating(function ($news) {
        $news->slug = Str::slug($news->subject);
        
    });

    static::created(function($news){
        $news->slug = Str::slug($news->subject).'-'.$news->id->save();
    });
    }

Just like this?

Snapey's avatar
Snapey
Best Answer
Level 122

created instead of creating

 protected static function boot() {
    parent::boot();

    static::created(function($news){
        $news->slug = Str::slug($news->subject).'-'.$news->id;
    $news->save();
    });
    }

henryoladj's avatar

@snapey Is it possible the ID does not show for the initial post and show only for the duplicate post?

Snapey's avatar

The problem is that you don't know its the initial post. The only way you would know is to query the database.

Its possible of course, but I would probably do it in the controller. If no post exists with that slug, populate the slug in the create() method then in this observer, check if slug is already set. If not, add the ID.

Or just do it all in the controller.

henryoladj's avatar

@snapey

 protected static function boot() {
    parent::boot();

    static::created(function($news){
        $news->slug = Str::slug($news->subject).'-'.$news->id;
    $news->save();
    });
    }

This is actually making the posts appear more than once, how can i resolve this?

henryoladj's avatar

@snapey I moved it to my controller

 public function store(Request $request)
    {
        //validate

        $this->validate($request,[
            'subject'=>'required|min:10',
            'tags' => 'required',
            'body' => 'required|min:20'

        ]);
        
        //store
        $news=auth()->user()->news()->create($request->all());

        $news->tags()->attach($request->tags);
        $news->slug = Str::slug($news->subject);
        $news->slug = Str::slug($news->subject).'-'.$news->id;
        $news->save();
        //redirect
        return redirect()->route('news.index');
    }

The initial post appears once with an ID but if i try to duplicate it then it appears twice with another ID

E.g First Post (localhost:8000/post/new-post-1) Second Post (localhost:8000/new-post-2) this one appears twice.

How can i resolve?

Snapey's avatar
public function store(Request $request)
    {
        //validate

        $this->validate($request,[
            'subject'=>'required|min:10',
            'tags' => 'required',
            'body' => 'required|min:20'

        ]);
        
        //store

        $previous = News::where('slug',Str::slug($news->subject))->count();

        $news=auth()->user()->news()->create($request->all());

        if($previous) {
            $news->slug = Str::slug($news->subject);
        } else {
            $news->slug = Str::slug($news->subject).'-'.$news->id;
        }

        $news->save();

        $news->tags()->attach($request->tags);
      
        //redirect
        return redirect()->route('news.index');
    }

adjust if your model is not called News

henryoladj's avatar

@snapey my Model is called News, but i am getting this error Undefined variable: news

from this line

$previous = News::where('slug',Str::slug($news->subject))->count();
Snapey's avatar

Sorry, the subject needs to come from the request. $news has not been created yet

$previous = News::where('slug',Str::slug($request->subject))->count();
henryoladj's avatar

@snapey it works fine now just that it still displays posts with same ID and slug 5 times...

henryoladj's avatar

Posts appears more than once after using sluggable

Snapey's avatar

When you do what? When you add more posts or when you edit the post?

jksantos's avatar

I recently had the same problem and researching I ended up here :D

Reading as posts, I decided to do it this way

$slug = Str::slug($request->title);
$numSlugs = Post::where('slug', 'regexp', '^'.$slug.'(-[0-9])?')->count();
if($numSlugs== 0) {
     $post->slug = $slug;
}else{
     $post->slug = $slug.'-'.$numSlugs;
}

This way the slug would not be repeated even if the title is repeated or in a way that the slug would be repeated.

Please or to participate in this conversation.