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

Entity Exist Laravel Package

k2gl/entity-exist

k2gl/entity-exist is a lightweight Laravel package for checking whether an entity exists before your app acts on it. It provides simple, reusable existence checks for guard clauses, validation flows, and safe record lookups, helping keep null-related errors out of your code.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the honest framing: this is a Symfony validation constraint backed by Doctrine ORM. It has no Laravel service provider, no Eloquent integration, and 0 dependents. For a Laravel codebase, day-to-day leverage is effectively zero — exists and unique already ship in the framework. The realistic scenarios where you'd touch this package are:

  1. You maintain a Symfony app (or a shared domain package) alongside Laravel services.
  2. You're evaluating it as a design reference for a Doctrine-backed or entity-aware validator.
  3. You want entity-level (not table-level) existence checks and are willing to bridge Doctrine into Laravel.

Minimal steps

composer require k2gl/entity-exist

No bundle registration is typically needed — Symfony autoconfigures anything implementing ConstraintValidatorInterface in src/. If the package ships a DependencyInjection extension, register the bundle instead; check composer.json for type: symfony-bundle.

Where to look first, in order:

  1. src/ — the constraint class (options) and the validator (the query it builds). This package is small enough to read end-to-end in ten minutes, and you should, because the README is likely thinner than you want.
  2. composer.json — supported symfony/validator and doctrine/orm ranges. This determines whether it will even install next to your framework version.
  3. tests/ — the authoritative source for option names, null handling, and message defaults.

First use case: validating a DTO or form backing object where a foreign-key-ish field must resolve to a real row — or, inverted, must not resolve (uniqueness on registration).

use K2gl\EntityExist\...; // confirm namespace/class name from src/

final class RegisterInput
{
    #[Assert\NotBlank]
    #[Assert\Email]
    #[EntityExist(entity: User::class, field: 'email', exist: false)]
    public string $email;
}

Then validate with the standard validator service:

$errors = $validator->validate($input);

Option names above are illustrative — verify entity, field, and the boolean flag against the constraint's constructor before writing more than one usage.

Implementation Patterns

Uniqueness on create. Set the "must not exist" mode and pair it with NotBlank. Keep the database unique index regardless — see gotchas.

Scope the lookup. Real existence checks are almost never global. A tenant-scoped slug or a per-account email needs additional criteria. Look for a criteria / extraFields option or a repository-method option in the constraint; if neither exists, that's your extension point (see below).

Exclude self on update. Editing an entity that already owns the value will fail a naive uniqueness check. Either pass the current ID as an exclusion criterion or use a custom repository method that filters id != :current.

Soft deletes. Doctrine soft-delete filters may or may not apply to the validator's query depending on whether it goes through the repository (filters apply) or a raw query builder (they may not). Be explicit: add deletedAt: null to criteria rather than relying on filter state.

Prefixed lookups. If the constraint reads the value from a property, you can point it at any property on the object — including ones computed by a getter, if it uses Symfony's PropertyAccessor. That's the one thing this package can express that Laravel's string-based exists:table,column cannot.

Bridging into Laravel (if you must). Don't drag Doctrine in for this. Instead, translate the intent into native rules:

public function rules(): array
{
    return [
        'email' => [
            'required', 'email',
            Rule::unique('users', 'email')->ignore($this->route('user')),
        ],
        'team_id' => ['required', Rule::exists('teams', 'id')
            ->whereNull('deleted_at')],
    ];
}

If you genuinely need the Symfony constraint (e.g., a shared DTO validated by both apps), write an adapter rule that resolves the target class to a table/column via Doctrine metadata and delegates to Rule::exists/Rule::unique. Keep the adapter thin; it's the only part you'll maintain.

Testing. The validator hits the database, so unit tests without a DB are noise. Use an in-memory SQLite connection with a minimal schema and assert on ConstraintViolation counts and paths, not on messages.

$violations = $validator->validate($dto);
self::assertCount(1, $violations);
self::assertSame('email', $violations[0]->getPropertyPath());

Batch imports. Never run this constraint per row in a loop for imports. Do one set-based query (whereIn) and build the error map yourself — it's an order of magnitude fewer round trips.

Gotchas and Tips

Maturity risk. 1 star, 0 dependents, and a release date that post-dates today — treat the metadata with suspicion and pin an exact version with a lock file. Read the source before trusting the API surface; it's small enough that this is cheap insurance.

It is not a data-integrity mechanism. "Check then insert" is a TOCTOU race. The constraint improves error UX; the unique index and foreign keys are what actually protect you. Never let the validator's presence justify dropping a DB constraint.

Every constraint is a query. One SELECT/COUNT per validated field per request. Watch your query log on forms with several entity-referencing fields; stack them and you'll notice.

Null handling. Most such constraints skip when the value is null/empty. Confirm the behavior and always pair with NotBlank, or you'll get "valid" empty values silently passing.

Pending unit-of-work state. The validator queries through the Doctrine manager. Unflushed changes in the current request may or may not be visible depending on auto-flush settings — validate before mutating, or flush first, deliberately.

Debugging in Symfony. bin/console debug:validator App\Entity\User prints the constraints attached to a class and its properties — the fastest way to confirm the attribute is actually registered and the options parsed as expected. For the query itself, enable the Doctrine SQL logger.

Extension points. Subclass the validator or the constraint when you need scoped lookups or self-exclusion — overriding validate() gives you full control while keeping the attribute ergonomics. The message option is the intended customization hook for i18n; wire it to your translation domain rather than hardcoding strings.

Config quirks to verify in src/: constructor argument order/defaults, whether the "must exist / must not exist" flag is a boolean or two separate constraints, whether the target is a class-string or a manager+entity pair (relevant for multi-entity-manager setups, where picking the wrong manager silently queries the wrong connection).

Bottom line for a Laravel dev: bookmark it as a reference implementation, not a dependency. Native rules plus a scoped Rule::exists()->where(...) cover the same ground with zero new surface area.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package