The error, I am observing, I try to put the old value i.e already stored. However, the case is, the old value get plucked with its own id, eachtime.
SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: tags.name (Connection: sqlite, SQL: insert into “tags” (“name”, “user_id”, “updated_at”, “created_at”) values (laravel, 1, 2024-12-13 05:16:56, 2024-12-13 05:16:56))
Here is what I am trying
$tag_ids = [];
foreach($tag_names as $tag_name) {//tag_names is array of tags
$tag = Tag::firstOrCreate([ //Tag is a Model
'name' => $tag_name,
'user_id' => auth()->id(),
]);
if($tag) {
$tag_ids[] = $tag->id;
}
}
Here is the Tag Model
class Tag extends Model {
protected $guarded = [];
public function user() {
return $this->belongsTo(User::class);
}
}
Here is the migration
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->foreignId('user_id')->constrained();
$table->timestamps();
});
1
To synchronise the tags you can use a single query insertOrIgnore()
and use another one to retrieve the ids.
$to_be_upserted = [];
foreach($tag_names as $tag_name) {
$to_be_upserted[] = ['name' => $tag_name, 'user_id' => auth()->id()];
}
Tag::query()->insertOrIgnore($to_be_upserted, []);
//here all the tags are present in DB
$tag_ids = Tag::query()->where('user_id', auth()->id())
->whereIn('name', $tag_names)
->pluck('id')->toArray();
If you get the mass assignment exception. You will need to add the fields name
and user_id
to the Tag model fillable attribute.
class Tag extends Model
{
$fillable = ['name','user_id'];
//...
}
Edit:
For your issue with the database, you should not have a unique constraint on the field name
in the table tags
since you want the name to be unique only to a specific user.
You can correct that in the existing migration if you can migrate from fresh.
If you can’t then add this new migration
Schema::table('tags', function(Blueprint $table)
{
$table->dropUnique(['name']);
$table->unique('name', 'user_id');
});
4
I see that you want to collect tag_id
based on tag_name
, so as stated here, I suggest something using firstOrCreate
as follows
$tag_ids = [];
foreach($tag_names as $tag_name) {//tag_names is array of tags
$tag = Tag::firstOrCreate(
['name' => $tag_name],
['user_id' => auth()->id()]
);
if($tag) {
$tag_ids[] = $tag->id;
}
}
by doing this, it will find by name
or create it with name
and user_id
.
8