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

Hasin Laravel Package

biiiiiigmonster/hasin

biiiiiigmonster/hasin brings recursive "has in" relationship queries to Laravel's Eloquent ORM, letting you fetch ancestors, descendants, and other nested tree data with fluent, hasMany-style syntax instead of raw recursive SQL. Ideal for category trees, comment threads, and org charts.

View on GitHub
Deep Wiki
Context7

Getting Started

biiiiiigmonster/hasin swaps Eloquent's where exists (...) correlation for a where in (subquery) — usually a large win on MySQL when the parent table is big and the relation key is indexed. v5.1.0 is a compatibility release: dependency bumps plus Laravel 13.x support (via Laravel Shift, follow-up fix in #66). There are no API changes, deprecations, or breaking changes for existing 5.x users.

  1. Install and let auto-discovery register the service provider:

    composer require biiiiiigmonster/hasin:^5.1
    
  2. Add the trait to every model whose relations you want to query this way:

    use BiiiiiigMonster\Hasin\HasIn;
    
    class User extends Model
    {
        use HasIn;
    }
    
  3. First use case — take a slow existing scope and swap the method name only:

    // before
    User::whereHas('posts', fn ($q) => $q->where('published', true))->paginate();
    
    // after
    User::whereHasIn('posts', fn ($q) => $q->where('published', true))->paginate();
    

Where to look first: ->toSql() on both variants for one of your real queries. The subquery shape (select ... where in (select ...)) is the whole package — if it doesn't change, the trait isn't loaded on that model or the relation is one the package delegates back to core Eloquent.

Implementation Patterns

Drop-in parity with whereHas. The trait exposes the familiar quartet, so a whole codebase can be migrated mechanically:

Core Eloquent hasin
whereHas / orWhereHas whereHasIn / orWhereHasIn
whereDoesntHave / orWhereDoesntHave whereDoesntHaveIn / orWhereDoesntHaveIn
has / orHas hasIn / orHasIn
doesntHave / orDoesntHave doesntHaveIn / orDoesntHaveIn

Nested relations. Dot notation and closures compose the same way, so multi-hop filters convert without rewriting:

User::whereHasIn('posts.comments', fn ($q) => $q->where('approved', true))->get();

Grouping with or. The classic precedence bug is unchanged — always wrap orWhereHasIn in a closure:

User::where('active', true)
    ->where(fn ($q) => $q
        ->whereHasIn('posts')
        ->orWhereHasIn('comments'))
    ->get();

Mixed with eager loading. Filters and with()/withCount() are independent; combine freely so one query set both filters and hydrates:

User::query()
    ->whereHasIn('posts', fn ($q) => $q->where('published', true))
    ->withCount('posts')
    ->with('posts:id,user_id,title')
    ->paginate(50);

Index-driven hot paths. Reach for whereHasIn on list/report endpoints where the parent set is large and the FK on the child table is indexed; leave whereHas on small or highly selective sets where the planner already short-circuits. A useful workflow is to convert one scope at a time behind a feature flag, compare EXPLAIN output, then roll forward.

Reusable scopes. Wrap the choice in a model scope so the decision is in one place and reversible if a future DB engine prefers exists:

public function scopePublished(Builder $q): Builder
{
    return $q->whereHasIn('posts', fn ($p) => $p->where('published', true));
}

Upgrading to Laravel 13. Bump to ^5.1 alongside the framework bump; nothing else in the package API moved from 5.0.1. Pin ^5.1 rather than ^5.0 if you're on L13 so you don't resolve a release without the fix from #66.

Gotchas and Tips

  • NOT IN and NULLs. whereDoesntHaveIn / doesntHaveIn can render as not in (subquery); if the subquery can yield a NULL key, the whole predicate evaluates to no rows. Confirm the generated SQL and, where relevant, constrain the subquery or fall back to whereDoesntHave.
  • No count operator. has('posts', '>=', 5) has no hasIn equivalent — keep core has() or use withCount(...)->having(...) for cardinality filters.
  • Semantics are equal, performance isn't. in (subquery) and exists return the same rows but can plan very differently. Benchmark on real data volume; on some engines/selectivity the rewrite is neutral or slower.
  • Trait per model. The methods live on the model, not globally. A relation queried through a model without use HasIn will error or fall through to core behaviour — check the trait first when a call "does nothing".
  • Relation query scopes still apply. Global scopes (soft deletes, tenant scopes) on the related model are inside the subquery, which is usually what you want — but an unset tenant scope will silently widen the IN list.
  • Grouping is on you. orWhereHasIn at the top level leaks across the whole WHERE, exactly like orWhereHas. Wrap in ->where(fn ($q) => ...).
  • Debugging recipe. ->dd() / ->toSql() plus EXPLAIN on the outer query is the fastest path; the parent key correlation shows up as the inner whereColumn-style constraint. If the subquery selects more than the relation key, something (a select() in your closure, a withCount) has contaminated it.
  • No config surface. Behaviour is trait-driven; there's no publishable config to tune, so treat the choice of In vs exists as an application-level decision and keep it behind scopes.
  • Pinning. ^5.1 requires a recent framework; if you run L10–L12 you can stay on the same line, but verify PHP constraints in composer.json before a broad bump in a monorepo.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core