Skip to content

[13.x] insertOrIgnoreReturning with multiple unique keys#59187

Merged
taylorotwell merged 5 commits intolaravel:13.xfrom
tpetry:fix/returning
Mar 14, 2026
Merged

[13.x] insertOrIgnoreReturning with multiple unique keys#59187
taylorotwell merged 5 commits intolaravel:13.xfrom
tpetry:fix/returning

Conversation

@tpetry
Copy link
Contributor

@tpetry tpetry commented Mar 13, 2026

PR #59025 added the insertOrIgnoreReturning method which allows inserting data and ignoring duplicate conflicts with the great PostgreSQL/SQLite feature of, .e.g., RETURNING * to get all inserted rows back.

But that PR introduced a new concept, namely the $uniqueBy param. The idea was, that you can limit the duplicate ignoring to specific unique columns/keys. But the problem is, you can only limit this logic to one unique key and you must use this feature. So the insertOrIgnoreReturning method behaves differently compared to insertOrIgnore:

  • You can't use the new method if you have more than one unique key
  • The method will throw duplicate key exceptions when a table has duplicate key errors and the key ignored by $uniqueBy is not the one triggering the error.

So after all, while insertOrIgnoreReturning is a great new feature, the new behaviour made switching from insertOrIgnore quite complicated - or impossible. I've discussed with @antonkomarev (the creator of PR #59025) on how to solve these issues by retaining the new $uniqueBy feature but making it optional for anyone as it is a niche feature.

The method signature has been changed that it can be used absolutely identical to insertOrIgnore and users are able to opt-in gradually to more features:

  • use $returning to limit the columns returned
  • use $uniqueBy to limit the duplicate detection to a specific unique key (or columns of a specific unique key)
// old
public function insertOrIgnoreReturning(
    array $values, 
    array|string $uniqueBy, 
    array $returning = ['*']
): Collection;

// new
public function insertOrIgnoreReturning(
    array $values, 
    array $returning = ['*']
    array|string|null $uniqueBy = null, 
): Collection;

// API of insertOrIgnore without Returning
public function insertOrIgnore(
    array $values
);

@tpetry
Copy link
Contributor Author

tpetry commented Mar 14, 2026

Based on feedback by @antonkomarev I've also changed the saveOrIgnore method that had been added which uses the new insertOrIgnoreReturning method:

The new method has now also been modified to be compatible with the save method:

// old:
public function saveOrIgnore(
    array|string$uniqueBy,
    array $options = [],
);

// new:
public function saveOrIgnore(
    array $options = [],
    array|string|null $uniqueBy = null,
);

// related:
save(array $options = [])

So saveOrIgnore has now the new same semantics which makes it more usefull to many approaches:

  • it can be used as a drop-in replacement to save
  • $uniqueBy can be used optionally to limit the duplicate detection to a specific unique key (or columns of a specific unique key)

@taylorotwell taylorotwell merged commit 8ed1300 into laravel:13.x Mar 14, 2026
52 checks passed
@antonkomarev
Copy link
Contributor

@tpetry thank you for your input! This feature will be much more flexible and useful for everybody.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants