Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Uniquewith Validator Laravel Package

felixkiss/uniquewith-validator

Laravel validation rule for uniqueness across multiple columns. The unique_with rule extends Laravel's built-in unique validator, letting you require combinations such as company_id and email to be unique together, with support for ignoring IDs, extra where clauses, and custom column names.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. felixkiss/uniquewith-validator is a deliberately thin adapter: one service provider that calls Validator::extend('unique_with', ...) and resolves the rule string into a query-builder where chain. It ships no models, no migrations, no config file, and no middleware, so it imposes essentially zero architectural footprint on an existing Laravel app. The problem it solves — "this value must be unique within a scope" — is a recurring one in multi-tenant SaaS and marketplace schemas (email unique per account, slug unique per site, SKU unique per vendor), and it is exactly the case where Laravel's default unique rule is insufficient out of the box.

Integration feasibility. High for the happy path. Installation is a single composer require, and Laravel package auto-discovery wires the provider. Usage is a string rule: 'email' => 'unique_with:users,account_id', with optional positional arguments for an ignored row ID and the primary key column on updates. The main caveat is that everything is positional and stringly-typed — readability and refactorability are poor, and the rule does not participate in the modern Rule object API.

Technical risk. The dominant risk is framework version drift, not code quality. The package's public surface is small and conceptually stable, but release notes/CI coverage need to be verified against our target Laravel major before anything else. Packages of this vintage frequently depend on global helpers that were removed in Laravel 6 (array_get, str_*) and on pre-Rule validation internals; if the last tagged release predates our runtime, we are effectively adopting unmaintained code. Secondary risks: the rule parses table and column names directly out of the rule string (safe when defined statically in code, a SQL-injection vector if anyone ever interpolates request input into it), and it offers no opinion on soft deletes or tenant global scopes.

Strategic read. The composite score (7.61) reflects a mature, well-understood utility; the opportunity score (3.03) reflects the fact that its core capability has been absorbed into the framework. Rule::unique('users')->where(fn ($q) => $q->where('account_id', $accountId))->ignore($id) covers the same ground with first-class framework support, IDE discoverability, and no third-party dependency. This package is a convenience, not a capability we cannot get elsewhere.

Key questions to resolve before adoption

  1. What is the newest tagged release, and which Laravel/PHP versions appear in its CI matrix? Has anyone exercised it on our target major in the last 12 months?
  2. Does it reference removed global helpers or other pre-Laravel-6 APIs?
  3. For every planned unique_with usage, does a matching composite unique index exist in the schema — and will we add it if not?
  4. How does it treat soft-deleted rows, nullable columns, and case-insensitive collations relative to the DB index semantics?
  5. Who maintains it, what is the issue-response cadence, and what is our fork-and-vendor cost if it stalls?

Integration Approach

Stack fit. Appropriate for Laravel 5.x–8.x-era applications that already express validation as pipe-delimited rule strings and where the team wants a one-line rule instead of a closure. It is a poorer fit for greenfield work on Laravel 9+, where Rule::unique() with where()/ignore() is idiomatic and avoids a dependency entirely. If our codebase already uses Rule objects or Form Requests with typed rule arrays, introducing a second, string-based idiom creates inconsistency for marginal gain.

Migration path. Treat this as a replace-or-adopt decision, not a one-way door — the package's entire surface is ~1–2 files and can be replicated in a handful of lines if the dependency sours.

  • Existing usages of unique_with (legacy app): keep the package if it passes compatibility testing; otherwise migrate each rule mechanically to Rule::unique(...)->where(...)->ignore(...). The mapping is one-to-one and scriptable — audit with a repo-wide search before starting.
  • Greenfield: skip the package; use native rules plus a DB constraint.
  • Fork option: if the package is incompatible but the syntax is entrenched across hundreds of rules, fork it, patch the helper calls, and vendor it as an internal package. At this code size that is a half-day job and a defensible middle path.

Compatibility. Two axes matter: Laravel major version and database driver. The query-builder path is portable across MySQL/PostgreSQL/SQLite, but semantics are not — see failure modes below. Verify against the actual driver in production, not SQLite in CI, because case sensitivity and NULL handling diverge sharply between them.

Sequencing

  1. Spike (0.5 day). Install on a branch pinned to our Laravel version; exercise create, update-with-ignore, and scoped-collision cases against a production-like DB.
  2. Schema audit (0.5–1 day). Confirm a composite unique index exists for every intended usage; add missing ones. This is the real correctness work and is independent of the package.
  3. Decision gate. Pass → adopt with a documented convention for rule syntax. Fail → vendor/fork or migrate to native Rule::unique.
  4. Rollout. Introduce rule-by-rule behind existing Form Requests; no user-visible change expected beyond improved error messages.
  5. Guardrail. Add a lint/review checklist item requiring a composite index for any new scoped-uniqueness rule.

Operational Impact

Maintenance. Low effort, low activity. The upside of a ~150-line package is that the maintenance surface is trivial and the fork cost is negligible. The downside is that upstream activity is likely minimal; assume no proactive fixes and budget a periodic (semi-annual) compatibility check tied to Laravel upgrade cycles. Pin the version in composer.json and let our dependency-update tooling surface breaks rather than floating it.

Support. Community-only: GitHub issues, no vendor SLA. Acceptable for a validator; escalate-worthy if the same logic ever gates financial or compliance-critical operations. Mitigation is the vendor/fork path, which is cheap here.

Scaling. One additional indexed SELECT per validated field per request — negligible at normal volumes provided the composite index exists. Without it, each validation is a table scan, which turns a cheap UX check into a latent performance cliff under load. The real scaling hazard is bulk operations: CSV imports, seeders, and queue jobs that validate row-by-row produce an N+1 query pattern. For bulk paths, bypass the validator and rely on insertOrIgnore/upsert against the unique index, translating constraint violations into a per-row report.

Failure modes

Failure Cause Mitigation
False "already taken" Validator sees rows the user shouldn't (soft-deleted, other tenant) Explicit scope columns in the rule; decide soft-delete policy
False "available", then 500 TOCTOU race between check and insert Enforce a DB composite unique index; catch QueryException (SQLSTATE 23000) and convert to a validation error
Inconsistent behavior across environments Case-insensitive MySQL collation vs case-sensitive Postgres/SQLite Test against production driver; normalize case pre-validation
Duplicate NULLs accepted by DB but rejected by validator SQL NULL != NULL semantics in unique indexes Define explicit nullable policy per field
Validation errors masking DB outages Connection failure surfaces through the validation path Verify behavior in the spike; ensure infra errors are distinguishable from user errors
Runtime error after upgrade Removed framework helpers Version pin + CI matrix on the target Laravel major

Ramp-up. Negligible. A Laravel developer is productive in under an hour; the only durable knowledge transfer needed is the convention: scoped uniqueness always means (a) a unique_with/Rule::unique scope on the rule and (b) a matching composite index, because the validator is a UX affordance and the index is the actual guarantee. Document that pairing, and the package's opacity stops mattering.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator