php - Laravel firstOrCreate issues

I have some problems with checking if some value exists in database and if not then to create it and return id, but every time when I write something like:

$attribute = AttributeValue::where('value', $value)->firstOrCreate([
                    'value' => $value,
                    'attribute_id' => $relation->attribute_id,
                    'default_order' => $next
                ]);

It gives error for duplicate entry, like:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'M' for key
'e_product_attributes_value_value_unique'

I also tried with firstOrNew, but it's not working good as well. Any ideas how to fix that?

Answer

Solution:

The most likely reason it's causing a unique key constraint error is because you're misusing firstOrCreate(). Your query should be

$attribute = AttributeValue::firstOrCreate(
    [
        'value' => $value,
    ],
    [
        'attribute_id' => $relation->attribute_id,
        'default_order' => $next,
    ]
);

Here's the source code for Eloquent Builder's .

    /**
     * Get the first record matching the attributes or create it.
     *
     * @param  array  $attributes
     * @param  array  $values
     * @return \Illuminate\Database\Eloquent\Model|static
     */
    public function firstOrCreate(array $attributes = [], array $values = [])
    {
        if (! is_null($instance = $this->where($attributes)->first())) {
            return $instance;
        }

        return tap($this->newModelInstance($attributes + $values), function ($instance) {
            $instance->save();
        });
    }

As you can see, it roughly translates to

$attribute = AttributeValue::where('value', $value)->first();

if ($attribute === null) {
    $attribute = AttributeValue::create([
        'value' => $value,
        'attribute_id' => $relation->attribute_id,
        'default_order' => $next,
    ]);
}

Source