PHPackages                             mpyw/eloquent-has-by-join - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. mpyw/eloquent-has-by-join

AbandonedArchivedLibrary[Database &amp; ORM](/categories/database)

mpyw/eloquent-has-by-join
=========================

Convert has() and whereHas() constraints to join() ones for single-result relations.

v2.0.2(3y ago)23133.8k↓41.4%4MITPHPPHP ^7.3 || ^8.0

Since Jun 27Pushed 2y ago2 watchersCompare

[ Source](https://github.com/mpyw/eloquent-has-by-join)[ Packagist](https://packagist.org/packages/mpyw/eloquent-has-by-join)[ RSS](/packages/mpyw-eloquent-has-by-join/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (7)Dependencies (7)Versions (9)Used By (0)

Eloquent Has By Join [![Build Status](https://github.com/mpyw/eloquent-has-by-join/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/mpyw/eloquent-has-by-join/actions) [![Coverage Status](https://camo.githubusercontent.com/8e739276e23da14039c299b8adef93ad0a80ea79ab78feb9195ef273ec3684ac/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6d7079772f656c6f7175656e742d6861732d62792d6a6f696e2f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/mpyw/eloquent-has-by-join?branch=master) [![Scrutinizer Code Quality](https://camo.githubusercontent.com/0fcea85bbcd1cade3dda51047234c197bd825b116ae9e06f0a1753d81de0944a/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d7079772f656c6f7175656e742d6861732d62792d6a6f696e2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mpyw/eloquent-has-by-join/?branch=master)
============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#eloquent-has-by-join---)

Convert `has()` and `whereHas()` constraints to `join()` ones for single-result relations.

Important

**NOTICE: Postgres' optimizer is very smart and covers JOIN optimization for dependent (correlated) subqueries. Therefore, this library is mainly targeted at MySQL which has a poor optimizer.**

Caution

**UPDATE: [MySQL's optimizer has also been updated in version `8.0.16`](https://zenn.dev/yumemi_inc/articles/e8ca9535dba0b6) to include optimizations similar to PostgreSQL. This library is no longer maintained.**

Requirements
------------

[](#requirements)

- PHP: `^7.3 || ^8.0`
- Laravel: `^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0`

Installing
----------

[](#installing)

```
composer require mpyw/eloquent-has-by-join
```

Motivation
----------

[](#motivation)

Suppose you have the following relationship:

```
class Post extends Model
{
    use SoftDeletes;
}
```

```
class Comment extends Model
{
    use SoftDeletes;

    public function post(): BelongsTo
    {
        return $this->belongsTo(Post::class);
    }
}
```

If you use `has()` constraints, your actual query would have **dependent subqueries**.

```
$comments = Comment::has('post')->get();
```

```
select * from `comments` where exists (
  select * from `posts`
  where `comments`.`post_id` = `posts`.`id`
    and `posts`.`deleted_at` is null
) and `comments`.`deleted_at` is null
```

These subqueries may cause performance degradations. This package provides **`Illuminate\Database\Eloquent\Builder::hasByJoin()`** macro to solve this problem: you can easily transform dependent subqueries into simple JOIN queries.

```
$comments = Comment::hasByJoin('post')->get();
```

```
select `comments`.* from `comments`
inner join `posts`
        on `comments`.`post_id` = `posts`.`id`
       and `posts`.`deleted_at` is null
where `comments`.`deleted_at` is null
```

API
---

[](#api)

### Signature

[](#signature)

```
Illuminate\Database\Eloquent\Builder::hasByJoin(string|string[] $relationMethod, ?callable ...$constraints): $this
```

### Arguments

[](#arguments)

#### `$relationMethod`

[](#relationmethod)

A relation method name that returns a **`BelongsTo`**, **`HasOne`** or **`MorphOne`** instance.

```
Builder::hasByJoin('post')
```

You can pass nested relations as an array or a string with dot-chain syntax.

```
Builder::hasByJoin(['post', 'author'])
```

```
Builder::hasByJoin('post.author')
```

You can provide table aliases with **`"as"`** syntax.

```
Builder::hasByJoin(['post as messages', 'author as message_authors'])
```

#### `$constraints`

[](#constraints)

Additional `callable` constraints for relations that take **`Illuminate\Database\Eloquent\Builder`** as the first argument.

```
Builder::hasByJoin('post', fn (Builder $query) => $query->withTrashed())
```

The first closure corresponds to `post` and the second one corresponds to `author`.

```
Builder::hasByJoin(
    'post.author',
    fn (Builder $query) => $query->withTrashed(),
    fn (Builder $query) => $query->whereKey(123)
)
```

Feature Comparison
------------------

[](#feature-comparison)

Feature`mpyw/eloquent-has-by-join`[`mpyw/eloquent-has-by-non-dependent-subquery`](https://github.com/mpyw/eloquent-has-by-non-dependent-subquery)Minimum Laravel version5.65.8Argument of optional constraints`Illuminate\Database\Eloquent\Builder``Illuminate\Database\Eloquent\Relations\*`
(`Builder` can be also accepted by specifying argument type)[Compoships](https://github.com/topclaudy/compoships) support✅❌No subqueries✅❌
(Performance depends on database optimizers)No table collisions❌
(Sometimes you need to give aliases)✅No column collisions❌
(Sometimes you need to use qualified column names)✅OR conditions❌✅Negative conditions❌✅Counting conditions❌❌`HasOne`✅✅`HasMany`❌✅`BelongsTo`✅✅`BelongsToMany`❌✅`MorphOne`✅✅`MorphMany`❌✅`MorphTo`❌❌`MorphMany`❌✅`MorphToMany`❌✅`HasOneThrough`❌✅`HasManyThrough`❌✅

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity41

Moderate usage in the ecosystem

Community13

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 90.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~106 days

Recently: every ~171 days

Total

8

Last Release

1404d ago

Major Versions

v1.1.3 → v2.0.02021-01-25

PHP version history (2 changes)v1.0.0PHP ^7.1

v2.0.0PHP ^7.3 || ^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1351893?v=4)[mpyw](/maintainers/mpyw)[@mpyw](https://github.com/mpyw)

---

Top Contributors

[![mpyw](https://avatars.githubusercontent.com/u/1351893?v=4)](https://github.com/mpyw "mpyw (20 commits)")[![chitoku-k](https://avatars.githubusercontent.com/u/6535425?v=4)](https://github.com/chitoku-k "chitoku-k (1 commits)")[![hexium310](https://avatars.githubusercontent.com/u/10758173?v=4)](https://github.com/hexium310 "hexium310 (1 commits)")

---

Tags

eloquentjoinlaravelperformancerelationshipslaraveldatabaseeloquentquerybuilderjoinilluminatemacrowhereHashas

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/mpyw-eloquent-has-by-join/health.svg)

```
[![Health](https://phpackages.com/badges/mpyw-eloquent-has-by-join/health.svg)](https://phpackages.com/packages/mpyw-eloquent-has-by-join)
```

###  Alternatives

[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k7.2M71](/packages/mongodb-laravel-mongodb)[kirschbaum-development/eloquent-power-joins

The Laravel magic applied to joins.

1.6k25.2M34](/packages/kirschbaum-development-eloquent-power-joins)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[mpyw/laravel-local-class-scope

A tiny macro that reuse a global scope class as a local scope

24102.6k](/packages/mpyw-laravel-local-class-scope)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[spiritix/lada-cache

A Redis based, automated and scalable database caching layer for Laravel

591444.8k2](/packages/spiritix-lada-cache)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
