cviebrock / eloquent-sluggable

Easy creation of slugs for your Eloquent models in Laravel
MIT License
3.89k stars 458 forks source link

Getting duplicate key error #230

Closed adrianb93 closed 8 years ago

adrianb93 commented 8 years ago

Hello,

I have been saving models in a for loop which is causing a duplicate key error. Essentially I have an array of id's which I use to create and save new models in a for loop. The slug is to be the date and time with no spaces or dashes 20160229101200, the error is below along with how I define my slug. I think sluggable is not checking if a slug already exists properly.

protected $sluggable = ['build_from' => 'generate_slug'];

public function getGenerateSlugAttribute()
{
    return preg_replace('/[^0-9]/', '', $this->created_at ?? date('Y-m-d H:i:s'));
}
QueryException in Connection.php line 651:
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value violates unique constraint "competency_data_slug_unique"
DETAIL: Key (slug)=(20160229095303-2) already exists. (SQL: insert into "competency_data" ("form_data", "group", "slug", "updated_at", "created_at") values ({}, 1, 20160229095303-2, 2016-02-29 09:53:03, 2016-02-29 09:53:03) returning "id")
adrianb93 commented 8 years ago

I am using version 3.1.4 of cviebrock/eloquent-sluggable.

Laravel 5.1

I am also using postgresql 9.4.

adrianb93 commented 8 years ago

Hello,

I've noticed that there are four possible results related to this issue. The results are random and inconsistent but always result in one of four of these:

I check four ids on my form, click submit and it either:

In my example I want to create more competencies that are related to a group, all competencies in a group must share the same information.

On all four of these scenarios I logged the form submission's ids and it is consistently correct as commented below, I also have logic to not add a row if it already exists which also works exactly as expected.

// CompetencyController@update
// $request->competencyids = [26, 27, 28, 29]
foreach ($request->competencyids as $competency_id) {
    if (! in_array($competency_id, $this->existingCompetencyIds($competency_data->group))) {
        $data = new CompetencyData;
        $data->form_data = $competency_data->form_data;
        $data->group     = $competency_data->group;
        $data->save();
    }
}
adrianb93 commented 8 years ago

Sorry, this was something entirely unexpected, I've been stepping through trying to figure out this issue and haven't seen anything wrong with what eloquent or sluggable is doing, turns out my client side validator is sending ajax requests to the update method on my controller as I submit my form.

https://github.com/proengsoft/laravel-jsvalidation

This is strange because it's been configured not do ajax form validation.

I resolved this for now by adding if ($request->ajax()) return;. My recommendation for others who experience this when even two seperate users submit a form on the same second is to rethink your slug to be a little more user specific or simply not to slug in this situation.