- How do I install staudenmeir/laravel-upsert in a Laravel app?
- Install it with composer require staudenmeir/laravel-upsert. The package uses Laravel package auto-discovery, so you do not need to register a service provider or publish configuration. It ships no migrations, so it will not change your schema. Once installed, call upsert() or insertIgnore() on the query builder or an Eloquent model.
- Do I need this package if I am already on Laravel 8.10 or newer?
- Laravel 8.10 added native upsert() and insertOrIgnore(), so if you are on 8.10+ with MySQL or PostgreSQL and only need the common case, the framework already covers it and the package is likely redundant. The package is most useful on older Laravel lines (roughly 5.5 to 8.9) or when you need its richer conflict-target and per-column update signatures, particularly on SQL Server. Treat adoption on newer Laravel as a redundancy decision rather than a capability gap.
- How do I specify custom unique-by columns for an upsert?
- Pass the conflict-target columns as the second argument: DB::table('users')->upsert($rows, ['email'], ['name', 'updated_at']). The second argument is your unique-by key and the third lists the columns to update on conflict. The package compiles the appropriate ON CONFLICT, ON DUPLICATE KEY UPDATE, or MERGE statement for the driver. Always inspect the generated SQL per driver, because conflict semantics are not equivalent.
- What is the difference between insertIgnore and insertOrIgnore?
- insertIgnore() inserts rows and silently skips any row that violates a unique or primary key constraint instead of throwing. Laravel 8.10+ ships insertOrIgnore() natively, while this package backports comparable behavior and adds insertGetId() with ignore support. On MySQL, INSERT IGNORE downgrades many errors, including truncation and foreign-key violations, to warnings, so pair it with validating your data before insert.
- Which databases does staudenmeir/laravel-upsert support, and are there caveats?
- It targets MySQL, PostgreSQL, SQLite, and SQL Server, but the emitted statements are not equivalent across engines. SQL Server MERGE has documented concurrency hazards, including duplicate-key violations under parallel load, and MySQL 8.0.20+ deprecated the VALUES(col) reference form that older upsert implementations emit. Run every driver and version you deploy in CI and review the generated SQL rather than assuming parity.
- Can I use upsert with Eloquent models and mass assignment?
- Yes. You can call upsert() on a model or through the query builder, and Eloquent mass assignment rules apply as they would to any insert. Automatic timestamps are not guaranteed for every upsert path, so include created_at and updated_at in your payload if you rely on them. For very large imports, DB::table()->upsert() avoids model hydration overhead.
- How do I control which columns get updated on a conflict?
- The third argument to upsert() is the list of columns to update when a conflict occurs; pass an empty array if you want conflicting rows left untouched. That lets you preserve counters, protect immutable columns, or refresh only updated_at. Check that the column ordering and expressions suit your driver, since the update list is compiled into driver-specific syntax.
- Is this package safe to run in production given its maintenance status?
- The last tagged release was in January 2022 and the project is effectively dormant, which is a compounding risk for a library that compiles SQL against four evolving engines. Validate compatibility with your current PHP, Laravel, and database versions before adopting it. Name an internal owner and keep an exit plan to migrate to native upsert() where available, and consider pinning versions or vendoring as a contingency.
- Does the package handle batching and bind-parameter limits for bulk upserts?
- It supports mass inserts but does not manage per-driver bind-parameter ceilings for you. MySQL, PostgreSQL, SQLite, and SQL Server each cap parameters per statement, and SQLite historically defaults to 999 while SQL Server allows 2100, so chunk rows so columns multiplied by rows stays under the limit. Own a small batching helper rather than assuming the package will split statements automatically.
- What alternatives should I consider before adding this dependency?
- On Laravel 8.10+ with MySQL or PostgreSQL, native upsert() and insertOrIgnore() are the default choice and this package becomes optional. Alternatives include driver-specific raw statements or a staging-table import library if you need heavier ETL behavior. If you specifically need custom conflict targets on older Laravel versions or SQL Server, this package remains a pragmatic option, but document how and when you will move to native support.