Full Code of biiiiiigmonster/hasin for AI

master 931dc68018e2 cached
67 files
88.0 KB
24.2k tokens
113 symbols
1 requests
Download .txt
Repository: biiiiiigmonster/hasin
Branch: master
Commit: 931dc68018e2
Files: 67
Total size: 88.0 KB

Directory structure:
gitextract_znsrf2cn/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── config.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── dependabot-auto-merge.yml
│       ├── fix-php-code-style-issues.yml
│       └── run-tests.yml
├── .gitignore
├── .scrutinizer.yml
├── CHANGELOG.md
├── LICENSE
├── README-CN.md
├── README.md
├── _laravel_ide_helper.php
├── composer.json
├── database/
│   ├── factories/
│   │   ├── CommentFactory.php
│   │   ├── CountryFactory.php
│   │   ├── HistoryFactory.php
│   │   ├── ImageFactory.php
│   │   ├── PhoneFactory.php
│   │   ├── PostFactory.php
│   │   ├── RoleFactory.php
│   │   ├── SupplierFactory.php
│   │   ├── TagFactory.php
│   │   ├── UserFactory.php
│   │   └── VideoFactory.php
│   └── migrations/
│       └── create_hasin_test_table.php
├── phpunit.xml.dist
├── pint.json
├── src/
│   ├── Database/
│   │   └── Eloquent/
│   │       ├── BuilderMixin.php
│   │       └── RelationMixin.php
│   └── HasinServiceProvider.php
└── tests/
    ├── Features/
    │   ├── DoesntHaveInTest.php
    │   ├── DoesntHaveMorphInTest.php
    │   ├── HasInTest.php
    │   ├── HasMorphInTest.php
    │   ├── OrDoesntHaveInTest.php
    │   ├── OrDoesntHaveMorphInTest.php
    │   ├── OrHasInTest.php
    │   ├── OrHasMorphInTest.php
    │   ├── OrWhereDoesntHaveInTest.php
    │   ├── OrWhereDoesntHaveMorphInTest.php
    │   ├── OrWhereHasInTest.php
    │   ├── OrWhereHasMorphInTest.php
    │   ├── OrWhereMorphRelationInTest.php
    │   ├── OrWhereRelationInTest.php
    │   ├── WhereDoesntHaveInTest.php
    │   ├── WhereDoesntHaveMorphInTest.php
    │   ├── WhereHasInTest.php
    │   ├── WhereHasMorphInTest.php
    │   ├── WhereMorphRelationInTest.php
    │   ├── WhereRelationInTest.php
    │   └── WithWhereHasInTest.php
    ├── Models/
    │   ├── Comment.php
    │   ├── Country.php
    │   ├── History.php
    │   ├── Image.php
    │   ├── Phone.php
    │   ├── Post.php
    │   ├── Role.php
    │   ├── RoleUser.php
    │   ├── Supplier.php
    │   ├── Tag.php
    │   ├── Taggable.php
    │   ├── User.php
    │   └── Video.php
    ├── Pest.php
    └── TestCase.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html

# Ignore all test and documentation with "export-ignore".
/.github            export-ignore
/.gitattributes     export-ignore
/.gitignore         export-ignore
/phpunit.xml        export-ignore
/phpunit.xml.dist   export-ignore
/art                export-ignore
/database           export-ignore
/docs               export-ignore
/tests              export-ignore
/.editorconfig      export-ignore
/.php_cs.dist.php   export-ignore
/psalm.xml          export-ignore
/psalm.xml.dist     export-ignore
/pint.json          export-ignore
/testbench.yaml     export-ignore
/UPGRADING.md       export-ignore
/phpstan.neon.dist  export-ignore
/phpstan-baseline.neon  export-ignore
/.scrutinizer.yml   export-ignore


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Ask a question
    url: https://github.com/biiiiiigmonster/hasin/discussions/new?category=q-a
    about: Ask the community for help
  - name: Request a feature
    url: https://github.com/biiiiiigmonster/hasin/discussions/new?category=ideas
    about: Share ideas for new features
  - name: Report a security issue
    url: https://github.com/biiiiiigmonster/hasin/security/policy
    about: Learn how to notify us for sensitive bugs
  - name: Report a bug
    url: https://github.com/biiiiiigmonster/hasin/issues/new
    about: Report a reproducable bug


================================================
FILE: .github/dependabot.yml
================================================
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:

  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    labels:
      - "dependencies"

================================================
FILE: .github/workflows/dependabot-auto-merge.yml
================================================
name: dependabot-auto-merge
on: pull_request_target

permissions:
  pull-requests: write
  contents: write

jobs:
  dependabot:
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'dependabot[bot]' }}
    steps:
    
      - name: Dependabot metadata
        id: metadata
        uses: dependabot/fetch-metadata@v2.5.0
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
          
      - name: Auto-merge Dependabot PRs for semver-minor updates
        if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
        run: gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
          
      - name: Auto-merge Dependabot PRs for semver-patch updates
        if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
        run: gh pr merge --auto --merge "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}


================================================
FILE: .github/workflows/fix-php-code-style-issues.yml
================================================
name: Fix PHP code style issues

on: [push]

jobs:
  php-code-styling:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          ref: ${{ github.head_ref }}

      - name: Fix PHP code style issues
        uses: aglipanci/laravel-pint-action@2.6

      - name: Commit changes
        uses: stefanzweifel/git-auto-commit-action@v7
        with:
          commit_message: Fix styling


================================================
FILE: .github/workflows/run-tests.yml
================================================
name: run-tests

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  test:
    runs-on: ${{ matrix.os }}

    services:
      mysql:
        image: mysql:5.7
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: laravel
        ports:
          - 33306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    strategy:
      fail-fast: true
      matrix:
        os: [ubuntu-latest]
        php: [8.2, 8.3, 8.4]
        laravel: ['12.*', '13.*']
        stability: [prefer-lowest, prefer-stable]
        include:
          - laravel: 12.*
            testbench: 10.*
          - laravel: 13.*
            testbench: 11.*
        exclude:
          - laravel: 13.*
            php: 8.2

    name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
          coverage: xdebug

      - name: Setup problem matchers
        run: |
          echo "::add-matcher::${{ runner.tool_cache }}/php.json"
          echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"

      - name: Install dependencies
        run: composer update --${{ matrix.stability }} --prefer-dist --no-interaction

      - name: Execute tests
        run: vendor/bin/pest
        env:
          DB_PORT: 33306
          DB_PASSWORD: root


================================================
FILE: .gitignore
================================================
.idea
.phpunit.result.cache
build
composer.lock
coverage
docs
phpunit.xml
testbench.yaml
vendor
node_modules
.phpunit.cache


================================================
FILE: .scrutinizer.yml
================================================
checks:
  php:
    code_rating: true
    remove_extra_empty_lines: true
    remove_php_closing_tag: true
    remove_trailing_whitespace: true
    fix_use_statements:
      remove_unused: true
      preserve_multiple: false
      preserve_blanklines: true
      order_alphabetically: true
    fix_linefeed: true
    fix_line_ending: true
    fix_identation_4spaces: true

build:
  image: default-bionic
  environment:
    php:
      version: 8.2
  tests:
    override:
      - command: './vendor/bin/pest'


================================================
FILE: CHANGELOG.md
================================================
# Changelog

All notable changes to `hasin` will be documented in this file.


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) Yunfeng Lu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README-CN.md
================================================
[English](./README.md) | 中文

<div align="center">

# LARAVEL HASIN

[![Latest Version on Packagist](https://img.shields.io/packagist/v/biiiiiigmonster/hasin.svg?style=flat-square)](https://packagist.org/packages/biiiiiigmonster/hasin)
[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/biiiiiigmonster/hasin/run-tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/biiiiiigmonster/hasin/actions?query=workflow%3Arun-tests+branch%3Amaster)
[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/biiiiiigmonster/hasin/fix-php-code-style-issues.yml?branch=master&label=code%20style&style=flat-square)](https://github.com/biiiiiigmonster/hasin/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amaster)
[![Coverage Status](https://coveralls.io/repos/github/biiiiiigmonster/hasin/badge.svg?branch=master)](https://coveralls.io/github/biiiiiigmonster/hasin?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/biiiiiigmonster/hasin.svg?label=Scrutinizer&style=flat-square)](https://scrutinizer-ci.com/g/biiiiiigmonster/hasin/)
[![Total Downloads](https://img.shields.io/packagist/dt/biiiiiigmonster/hasin.svg?style=flat-square)](https://packagist.org/packages/biiiiiigmonster/hasin)

</div>

`hasin`是一个基于`where in`语法实现的`Laravel ORM`关联关系查询的扩展包,部分业务场景下可以替代`Laravel ORM`中基于`where exists`语法实现的`has`,以获取更高的性能。

## 安装

| Laravel 版本      | 安装命令                                                |
|-----------------|-----------------------------------------------------|
| Laravel 12      | ``` composer require biiiiiigmonster/hasin:^5.0 ``` |
| Laravel 11      | ``` composer require biiiiiigmonster/hasin:^4.0 ``` |
| Laravel 10      | ``` composer require biiiiiigmonster/hasin:^3.0 ``` |
| Laravel 9       | ``` composer require biiiiiigmonster/hasin:^2.0 ``` |
| Laravel 5.5 ~ 8 | ``` composer require biiiiiigmonster/hasin:^1.0 ``` |

## 简介

`Laravel ORM`的关联关系非常强大,基于关联关系的查询`has`也给我们提供了诸多灵活的调用方式,然而某些情形下,`has`使用了**where exists**语法实现

例如:
```php
// User hasMany Post
User::has('posts')->get();
```
#### `select * from users where exists (select * from posts where users.id = posts.user_id)`
> exists是对外表做loop循环,每次loop循环再对内表(子查询)进行查询,那么因为对内表的查询使用的索引(内表效率高,故可用大表),而外表有多大都需要遍历,不可避免(尽量用小表),故内表大的使用exists,可加快效率。

当**User表**数据量较大的时候,就会出现性能问题,那么这时候用**where in**语法将会极大的提高性能

#### `select * from users where users.id in (select posts.user_id from posts)`
> in是把外表和内表做hash连接,先查询内表,再把内表结果与外表匹配,对外表使用索引(外表效率高,可用大表),而内表多大都需要查询,不可避免,故外表大的使用in,可加快效率。

因此在代码中使用`has(hasMorph)`或者`hasIn(hasMorphIn)`应由**数据体量**来决定……

```php
/**
 * SQL:
 * 
 * select * from `users` 
 * where exists 
 *   ( 
 *      select * from `posts` 
 *      where `users`.`id` = `posts`.`user_id` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::has('posts')->paginate(10);

/**
 * SQL:
 * 
 * select * from `users` 
 * where `users`.`id` in  
 *   ( 
 *      select `posts`.`user_id` from `posts` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::hasIn('posts')->paginate(10);
```

## 使用

此扩展方法`hasIn(hasMorphIn)`支持`Laravel ORM`中的所有关联关系,入参调用及内部实现流程与框架的`has(hasMorph)`完全一致。

> hasIn

```php
// hasIn
User::hasIn('posts')->get();

// orHasIn
User::where('age', '>', 18)->orHasIn('posts')->get();

// doesntHaveIn
User::doesntHaveIn('posts')->get();

// orDoesntHaveIn
User::where('age', '>', 18)->orDoesntHaveIn('posts')->get();
```

> whereHasIn

```php
// whereHasIn
User::whereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereHasIn
User::where('age', '>', 18)->orWhereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// whereDoesntHaveIn
User::whereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereDoesntHaveIn
User::where('age', '>', 18)->orWhereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();
```

> hasMorphIn

```php
Image::hasMorphIn('imageable', [Post::class, Comment::class])->get();
```

### 嵌套关联

```php
User::hasIn('posts.comments')->get();
```

## 测试
```bash
composer test
```

## 联系交流
wx:biiiiiigmonster(备注:hasin)

## 协议
[MIT 协议](LICENSE)


================================================
FILE: README.md
================================================
English | [中文](./README-CN.md)

<div align="center">

# LARAVEL HASIN

[![Latest Version on Packagist](https://img.shields.io/packagist/v/biiiiiigmonster/hasin.svg?style=flat-square)](https://packagist.org/packages/biiiiiigmonster/hasin)
[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/biiiiiigmonster/hasin/run-tests.yml?branch=master&label=tests&style=flat-square)](https://github.com/biiiiiigmonster/hasin/actions?query=workflow%3Arun-tests+branch%3Amaster)
[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/biiiiiigmonster/hasin/fix-php-code-style-issues.yml?branch=master&label=code%20style&style=flat-square)](https://github.com/biiiiiigmonster/hasin/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amaster)
[![Coverage Status](https://coveralls.io/repos/github/biiiiiigmonster/hasin/badge.svg?branch=master)](https://coveralls.io/github/biiiiiigmonster/hasin?branch=master)
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/biiiiiigmonster/hasin.svg?label=Scrutinizer&style=flat-square)](https://scrutinizer-ci.com/g/biiiiiigmonster/hasin/)
[![Total Downloads](https://img.shields.io/packagist/dt/biiiiiigmonster/hasin.svg?style=flat-square)](https://packagist.org/packages/biiiiiigmonster/hasin)

</div>

The `hasin` is composer package based on `where in` syntax to query the relationship of `laravel ORM`, which can replace `has` based on `where exists` syntax in some business scenarios to obtain higher performance.

# Installation
| Laravel Version | Install command                                     |
|-----------------|-----------------------------------------------------|
| Laravel 12      | ``` composer require biiiiiigmonster/hasin:^5.0 ``` |
| Laravel 11      | ``` composer require biiiiiigmonster/hasin:^4.0 ``` |
| Laravel 10      | ``` composer require biiiiiigmonster/hasin:^3.0 ``` |
| Laravel 9       | ``` composer require biiiiiigmonster/hasin:^2.0 ``` |
| Laravel 5.5 ~ 8 | ``` composer require biiiiiigmonster/hasin:^1.0 ``` |

# Introductions

The relationship of `laravel ORM` is very powerful, and the query `has` based on the relationship also provides us with many flexible calling methods. However, in some cases, `has` is implemented with **where exists** syntax.

For example:
```php
// User hasMany Post
User::has('posts')->get();
```
#### `select * from users where exists (select * from posts where users.id = posts.user_id)`
> 'exists' is a loop to the external table, and then queries the internal table (subQuery) every time. Because the index used for the query of the internal table (the internal table is efficient, so it can be used as a large table), and how much of the external table needs to be traversed, it is inevitable (try to use a small table), so the use of exists for the large internal table can speed up the efficiency.

When the **User** table has a large amount of data, there will be performance problems, so the **where in** syntax will greatly improve the performance.

#### `select * from users where users.id in (select posts.user_id from posts)`
> 'in' is to hash connect the appearance and inner table, first query the inner table, then match the result of the inner table with the appearance, and use the index for the outer table (the appearance is efficient, and large tables can be used). Most of the inner tables need to be queried, which is inevitable. Therefore, using 'in' with large appearance can speed up the efficiency.

Therefore, the use of `has(hasMorph)` or `hasIn(hasMorphIn)` in code should be determined by **data size**

```php
/**
 * SQL:
 * 
 * select * from `users` 
 * where exists 
 *   ( 
 *      select * from `posts` 
 *      where `users`.`id` = `posts`.`user_id` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::has('posts')->paginate(10);

/**
 * SQL:
 * 
 * select * from `users` 
 * where `users`.`id` in  
 *   ( 
 *      select `posts`.`user_id` from `posts` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::hasIn('posts')->paginate(10);
```

# Usage example

`hasIn(hasMorphIn)` supports all `Relations` in `laravel ORM`. The call mode and internal implementation are completely consistent with `has(hasMorph)` of the framework.

> hasIn

```php
// hasIn
User::hasIn('posts')->get();

// orHasIn
User::where('age', '>', 18)->orHasIn('posts')->get();

// doesntHaveIn
User::doesntHaveIn('posts')->get();

// orDoesntHaveIn
User::where('age', '>', 18)->orDoesntHaveIn('posts')->get();
```

> whereHasIn

```php
// whereHasIn
User::whereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereHasIn
User::where('age', '>', 18)->orWhereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// whereDoesntHaveIn
User::whereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereDoesntHaveIn
User::where('age', '>', 18)->orWhereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();
```

> hasMorphIn

```php
Image::hasMorphIn('imageable', [Post::class, Comment::class])->get();
```

### Nested Relation

```php
User::hasIn('posts.comments')->get();
```

# Testing
```bash
composer test
```
>**Tips**: before testing, you need to configure your database connection in the `phpunit.xml.dist`.

# License
[MIT](./LICENSE)


================================================
FILE: _laravel_ide_helper.php
================================================
<?php

namespace Illuminate\Database\Eloquent
{
    use Closure;

    if (false) {
        class Builder
        {
            /**
             * Add a relationship count / whereIn condition to the query.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\Relation|string  $relation
             * @param  string  $operator
             * @param  int  $count
             * @param  string  $boolean
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @throws \RuntimeException
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function hasIn($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with an "or".
             *
             * @param  string  $relation
             * @param  string  $operator
             * @param  int  $count
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orHasIn($relation, $operator = '>=', $count = 1)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query.
             *
             * @param  string  $relation
             * @param  string  $boolean
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function doesntHaveIn($relation, $boolean = 'and', Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with an "or".
             *
             * @return Closure
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orDoesntHaveIn()
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with where clauses.
             *
             * @param  string  $relation
             * @param  \Closure|null  $callback
             * @param  string  $operator
             * @param  int  $count
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function whereHasIn($relation, Closure $callback = null, $operator = '>=', $count = 1)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with where clauses and an "or".
             *
             * @param  string  $relation
             * @param  \Closure|null  $callback
             * @param  string  $operator
             * @param  int  $count
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orWhereHasIn($relation, Closure $callback = null, $operator = '>=', $count = 1)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with where clauses.
             *
             * @param  string  $relation
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function whereDoesntHaveIn($relation, Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a relationship count / whereIn condition to the query with where clauses and an "or".
             *
             * @param  string  $relation
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orWhereDoesntHaveIn($relation, Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  string  $operator
             * @param  int  $count
             * @param  string  $boolean
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function hasMorphIn($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with an "or".
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  string  $operator
             * @param  int  $count
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orHasMorphIn($relation, $types, $operator = '>=', $count = 1)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  string  $boolean
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function doesntHaveMorphIn($relation, $types, $boolean = 'and', Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with an "or".
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orDoesntHaveMorphIn($relation, $types)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with where clauses.
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             *
             * @return Closure
             */
            public function whereHasMorphIn()
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with where clauses.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  \Closure|null  $callback
             * @param  string  $operator
             * @param  int  $count
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orWhereHasMorphIn($relation, $types, Closure $callback = null, $operator = '>=', $count = 1)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with where clauses.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function whereDoesntHaveMorphIn($relation, $types, Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship count / whereIn condition to the query with where clauses and an "or".
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  \Closure|null  $callback
             * @return \Illuminate\Database\Eloquent\Builder|static
             *
             * @see \BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin
             */
            public function orWhereDoesntHaveMorphIn($relation, $types, Closure $callback = null)
            {
                return $this;
            }

            /**
             * Add a basic where clause to a relationship query.
             *
             * @param  string  $relation
             * @param  \Closure|string|array|\Illuminate\Database\Query\Expression  $column
             * @param  mixed  $operator
             * @param  mixed  $value
             * @return \Illuminate\Database\Eloquent\Builder|static
             */
            public function whereRelationIn($relation, $column, $operator = null, $value = null)
            {
                return $this;
            }

            /**
             * Add an "or where" clause to a relationship query.
             *
             * @param  string  $relation
             * @param  \Closure|string|array|\Illuminate\Database\Query\Expression  $column
             * @param  mixed  $operator
             * @param  mixed  $value
             * @return \Illuminate\Database\Eloquent\Builder|static
             */
            public function orWhereRelationIn($relation, $column, $operator = null, $value = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship condition to the query with a where clause.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  \Closure|string|array|\Illuminate\Database\Query\Expression  $column
             * @param  mixed  $operator
             * @param  mixed  $value
             * @return \Illuminate\Database\Eloquent\Builder|static
             */
            public function whereMorphRelationIn($relation, $types, $column, $operator = null, $value = null)
            {
                return $this;
            }

            /**
             * Add a polymorphic relationship condition to the query with an "or where" clause.
             *
             * @param  \Illuminate\Database\Eloquent\Relations\MorphTo|string  $relation
             * @param  string|array  $types
             * @param  \Closure|string|array|\Illuminate\Database\Query\Expression  $column
             * @param  mixed  $operator
             * @param  mixed  $value
             * @return \Illuminate\Database\Eloquent\Builder|static
             */
            public function orWhereMorphRelationIn($relation, $types, $column, $operator = null, $value = null)
            {
                return $this;
            }
        }
    }
}


================================================
FILE: composer.json
================================================
{
    "name": "biiiiiigmonster/hasin",
    "description": "Laravel framework relation has in implement",
    "type": "library",
    "keywords": [
        "laravel",
        "orm",
        "relation",
        "whereHas"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "YunFeng Lu",
            "email": "603707288@qq.com"
        }
    ],
    "require": {
        "laravel/framework": "^12|^13.0"
    },
    "require-dev": {
        "laravel/pint": "^1.1",
        "orchestra/testbench": "^10.0|^11.0",
        "pestphp/pest": "^3.0|^4.4",
        "pestphp/pest-plugin-laravel": "^3.0|^4.1"
    },
    "autoload": {
        "psr-4": {
            "BiiiiiigMonster\\Hasin\\": "src",
            "BiiiiiigMonster\\Hasin\\Database\\Factories\\": "database/factories"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "BiiiiiigMonster\\Hasin\\Tests\\": "tests"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "BiiiiiigMonster\\Hasin\\HasinServiceProvider"
            ]
        }
    },
    "scripts": {
        "test": "vendor/bin/pest",
        "format": "vendor/bin/pint"
    },
    "config": {
        "sort-packages": true,
        "allow-plugins": true
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}


================================================
FILE: database/factories/CommentFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use Illuminate\Database\Eloquent\Factories\Factory;

class CommentFactory extends Factory
{
    protected $model = Comment::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'content' => $this->faker->sentence,
            'status' => $this->faker->numberBetween(0, 9),
        ];
    }
}


================================================
FILE: database/factories/CountryFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Country;
use Illuminate\Database\Eloquent\Factories\Factory;

class CountryFactory extends Factory
{
    protected $model = Country::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->country
        ];
    }
}


================================================
FILE: database/factories/HistoryFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\History;
use Illuminate\Database\Eloquent\Factories\Factory;

class HistoryFactory extends Factory
{
    protected $model = History::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'content' => $this->faker->address
        ];
    }
}


================================================
FILE: database/factories/ImageFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Image;
use Illuminate\Database\Eloquent\Factories\Factory;

class ImageFactory extends Factory
{
    protected $model = Image::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'url' => $this->faker->url
        ];
    }
}


================================================
FILE: database/factories/PhoneFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Phone;
use Illuminate\Database\Eloquent\Factories\Factory;

class PhoneFactory extends Factory
{
    protected $model = Phone::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'phone_number' => $this->faker->phoneNumber
        ];
    }
}


================================================
FILE: database/factories/PostFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;

class PostFactory extends Factory
{
    protected $model = Post::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'title' => $this->faker->title,
            'votes' => $this->faker->numberBetween(0, 100),
        ];
    }
}


================================================
FILE: database/factories/RoleFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Role;
use Illuminate\Database\Eloquent\Factories\Factory;

class RoleFactory extends Factory
{
    protected $model = Role::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name
        ];
    }
}


================================================
FILE: database/factories/SupplierFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Supplier;
use Illuminate\Database\Eloquent\Factories\Factory;

class SupplierFactory extends Factory
{
    protected $model = Supplier::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name
        ];
    }
}


================================================
FILE: database/factories/TagFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Tag;
use Illuminate\Database\Eloquent\Factories\Factory;

class TagFactory extends Factory
{
    protected $model = Tag::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name
        ];
    }
}


================================================
FILE: database/factories/UserFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

class UserFactory extends Factory
{
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'username' => $this->faker->userName,
            'age' => $this->faker->numberBetween(10, 30),
        ];
    }
}


================================================
FILE: database/factories/VideoFactory.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Factories;

use BiiiiiigMonster\Hasin\Tests\Models\Video;
use Illuminate\Database\Eloquent\Factories\Factory;

class VideoFactory extends Factory
{
    protected $model = Video::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name
        ];
    }
}


================================================
FILE: database/migrations/create_hasin_test_table.php
================================================
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class () extends Migration {
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('histories', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->default(0);
            $table->string('content');
            $table->timestamps();
        });
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->morphs('commentable');
            $table->string('content');
            $table->tinyInteger('status')->default(0);
            $table->timestamps();
        });
        Schema::create('countries', function (Blueprint $table) {
            $table->id();
            $table->string('name')->default('');
            $table->timestamps();
        });
        Schema::create('images', function (Blueprint $table) {
            $table->id();
            $table->string('url')->default('');
            $table->morphs('imageable');
            $table->timestamps();
        });
        Schema::create('phones', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->default(0);
            $table->string('phone_number')->default('');
            $table->timestamps();
        });
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
        Schema::create('role_user', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->default(0);
            $table->bigInteger('role_id')->default(0);
            $table->timestamps();
        });
        Schema::create('suppliers', function (Blueprint $table) {
            $table->id();
            $table->string('name')->default('');
            $table->timestamps();
        });
        Schema::create('tags', function (Blueprint $table) {
            $table->id();
            $table->string('name')->default('');
            $table->timestamps();
        });
        Schema::create('taggables', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('tag_id')->default(0);
            $table->morphs('taggable');
            $table->timestamps();
        });
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('username')->default('');
            $table->tinyInteger('age')->default(0);
            $table->bigInteger('country_id')->default(0);
            $table->bigInteger('supplier_id')->default(0);
            $table->timestamps();
        });
        Schema::create('videos', function (Blueprint $table) {
            $table->id();
            $table->string('name')->default('');
            $table->timestamps();
        });
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->default(0);
            $table->string('title')->default('');
            $table->integer('votes')->default(0);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('histories');
        Schema::dropIfExists('comments');
        Schema::dropIfExists('countries');
        Schema::dropIfExists('images');
        Schema::dropIfExists('phones');
        Schema::dropIfExists('roles');
        Schema::dropIfExists('role_user');
        Schema::dropIfExists('suppliers');
        Schema::dropIfExists('tags');
        Schema::dropIfExists('taggables');
        Schema::dropIfExists('users');
        Schema::dropIfExists('videos');
        Schema::dropIfExists('posts');
    }
};


================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
    backupGlobals="false"
    bootstrap="vendor/autoload.php"
    colors="true"
    processIsolation="false"
    stopOnFailure="false"
    executionOrder="random"
    failOnWarning="true"
    failOnRisky="true"
    failOnEmptyTestSuite="true"
    beStrictAboutOutputDuringTests="true"
    cacheDirectory=".phpunit.cache"
    backupStaticProperties="false"
>
    <testsuites>
        <testsuite name="Hasin Test Suite">
            <directory suffix="Test.php">tests</directory>
        </testsuite>
    </testsuites>
    <coverage>
        <report>
            <html outputDirectory="build/coverage"/>
            <text outputFile="build/coverage.txt"/>
            <clover outputFile="build/logs/clover.xml"/>
        </report>
    </coverage>
    <source>
        <include>
            <directory suffix=".php">./src</directory>
        </include>
    </source>
    <logging>
        <junit outputFile="build/report.junit.xml"/>
    </logging>
    <php>
        <env name="DB_HOST" value="127.0.0.1"/>
        <env name="DB_PORT" value="3306"/>
        <env name="DB_DATABASE" value="laravel"/>
        <env name="DB_USERNAME" value="root"/>
        <env name="DB_PASSWORD" value="root"/>
    </php>
</phpunit>


================================================
FILE: pint.json
================================================
{
    "preset": "psr12",
    "exclude": [
        "build"
    ]
}


================================================
FILE: src/Database/Eloquent/BuilderMixin.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Eloquent;

use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Str;

class BuilderMixin
{
    /**
     * Add a relationship count / whereIn condition to the query.
     *
     * @return Closure
     */
    public function hasIn(): Closure
    {
        return function ($relation, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null): Builder {
            /** @var Builder $this */
            if (is_string($relation)) {
                if (str_contains($relation, '.')) {
                    return $this->hasInNested($relation, $operator, $count, $boolean, $callback);
                }

                $relation = $this->getRelationWithoutConstraints($relation);
            }

            if ($relation instanceof MorphTo) {
                return $this->hasMorphIn($relation, ['*'], $operator, $count, $boolean, $callback);
            }

            // If we only need to check for the existence of the relation, then we can optimize
            // the subquery to only run a "where in" clause instead of this full "count"
            // clause. This will make these queries run much faster compared with a count.
            $method = $this->canUseExistsForExistenceCheck($operator, $count)
                            ? 'getRelationExistenceInQuery'
                            : 'getRelationExistenceCountQuery';

            $hasInQuery = $relation->{$method}(
                $relation->getRelated()->newQueryWithoutRelationships(),
                $this
            );

            // Next we will call any given callback as an "anonymous" scope so they can get the
            // proper logical grouping of the where clauses if needed by this Eloquent query
            // builder. Then, we will be ready to finalize and return this query instance.
            if ($callback) {
                $hasInQuery->callScope($callback);
            }

            return $this->addHasInWhere(
                $hasInQuery,
                $relation,
                $operator,
                $count,
                $boolean
            );
        };
    }

    /**
     * Add nested relationship count / whereIn conditions to the query.
     *
     * Sets up recursive call to whereHas until we finish the nested relation.
     *
     * @return Closure
     */
    protected function hasInNested(): Closure
    {
        return function ($relations, $operator = '>=', $count = 1, $boolean = 'and', $callback = null): Builder {
            /** @var Builder $this */
            $relations = explode('.', $relations);

            $doesntHave = $operator === '<' && $count === 1;

            if ($doesntHave) {
                $operator = '>=';
                $count = 1;
            }

            $closure = function ($q) use (&$closure, &$relations, $operator, $count, $callback) {
                // In order to nest "hasIn", we need to add count relation constraints on the
                // callback Closure. We'll do this by simply passing the Closure its own
                // reference to itself so it calls itself recursively on each segment.
                count($relations) > 1
                    ? $q->whereHasIn(array_shift($relations), $closure)
                    : $q->hasIn(array_shift($relations), $operator, $count, 'and', $callback);
            };

            return $this->hasIn(array_shift($relations), $doesntHave ? '<' : '>=', 1, $boolean, $closure);
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with an "or".
     *
     * @return Closure
     */
    public function orHasIn(): Closure
    {
        return function ($relation, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasIn($relation, $operator, $count, 'or');
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query.
     *
     * @return Closure
     */
    public function doesntHaveIn(): Closure
    {
        return function ($relation, $boolean = 'and', ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->hasIn($relation, '<', 1, $boolean, $callback);
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with an "or".
     *
     * @return Closure
     */
    public function orDoesntHaveIn(): Closure
    {
        return function ($relation): Builder {
            /** @var Builder $this */
            return $this->doesntHaveIn($relation, 'or');
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with where clauses.
     *
     * @return Closure
     */
    public function whereHasIn(): Closure
    {
        return function ($relation, ?Closure $callback = null, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasIn($relation, $operator, $count, 'and', $callback);
        };
    }

    /**
     * Add a relationship count / exists condition to the query with whereIn clauses.
     *
     * Also load the relationship with same condition.
     *
     * @return Closure
     */
    public function withWhereHasIn(): Closure
    {
        return function ($relation, ?Closure $callback = null, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->whereHasIn(Str::before($relation, ':'), $callback, $operator, $count)
                ->with($callback ? [$relation => fn ($query) => $callback($query)] : $relation);
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with where clauses and an "or".
     *
     * @return Closure
     */
    public function orWhereHasIn(): Closure
    {
        return function ($relation, ?Closure $callback = null, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasIn($relation, $operator, $count, 'or', $callback);
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with where clauses.
     *
     * @return Closure
     */
    public function whereDoesntHaveIn(): Closure
    {
        return function ($relation, ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->doesntHaveIn($relation, 'and', $callback);
        };
    }

    /**
     * Add a relationship count / whereIn condition to the query with where clauses and an "or".
     *
     * @return Closure
     */
    public function orWhereDoesntHaveIn(): Closure
    {
        return function ($relation, ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->doesntHaveIn($relation, 'or', $callback);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query.
     *
     * @return Closure
     */
    public function hasMorphIn(): Closure
    {
        return function ($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', ?Closure $callback = null): Builder {
            /** @var Builder $this */
            if (is_string($relation)) {
                $relation = $this->getRelationWithoutConstraints($relation);
            }

            $types = (array) $types;

            if ($types === ['*']) {
                $types = $this->model->newModelQuery()->distinct()->pluck($relation->getMorphType())->filter()->all();
            }

            foreach ($types as &$type) {
                $type = Relation::getMorphedModel($type) ?? $type;
            }

            return $this->where(function ($query) use ($relation, $callback, $operator, $count, $types) {
                foreach ($types as $type) {
                    $query->orWhere(function ($query) use ($relation, $callback, $operator, $count, $type) {
                        $belongsTo = $this->getBelongsToRelation($relation, $type);

                        if ($callback) {
                            $callback = function ($query) use ($callback, $type) {
                                return $callback($query, $type);
                            };
                        }

                        $query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type())->getMorphClass())
                            ->whereHasIn($belongsTo, $callback, $operator, $count);
                    });
                }
            }, null, null, $boolean);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with an "or".
     *
     * @return Closure
     */
    public function orHasMorphIn(): Closure
    {
        return function ($relation, $types, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasMorphIn($relation, $types, $operator, $count, 'or');
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query.
     *
     * @return Closure
     */
    public function doesntHaveMorphIn(): Closure
    {
        return function ($relation, $types, $boolean = 'and', ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->hasMorphIn($relation, $types, '<', 1, $boolean, $callback);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with an "or".
     *
     * @return Closure
     */
    public function orDoesntHaveMorphIn(): Closure
    {
        return function ($relation, $types): Builder {
            /** @var Builder $this */
            return $this->doesntHaveMorphIn($relation, $types, 'or');
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with where clauses.
     *
     * @return Closure
     */
    public function whereHasMorphIn(): Closure
    {
        return function ($relation, $types, ?Closure $callback = null, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasMorphIn($relation, $types, $operator, $count, 'and', $callback);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with where clauses and an "or".
     *
     * @return Closure
     */
    public function orWhereHasMorphIn(): Closure
    {
        return function ($relation, $types, ?Closure $callback = null, $operator = '>=', $count = 1): Builder {
            /** @var Builder $this */
            return $this->hasMorphIn($relation, $types, $operator, $count, 'or', $callback);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with where clauses.
     *
     * @return Closure
     */
    public function whereDoesntHaveMorphIn(): Closure
    {
        return function ($relation, $types, ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->doesntHaveMorphIn($relation, $types, 'and', $callback);
        };
    }

    /**
     * Add a polymorphic relationship count / whereIn condition to the query with where clauses and an "or".
     *
     * @return Closure
     */
    public function orWhereDoesntHaveMorphIn(): Closure
    {
        return function ($relation, $types, ?Closure $callback = null): Builder {
            /** @var Builder $this */
            return $this->doesntHaveMorphIn($relation, $types, 'or', $callback);
        };
    }

    /**
     * Add a basic where clause to a relationship query.
     *
     * @return Closure
     */
    public function whereRelationIn(): Closure
    {
        return function ($relation, $column, $operator = null, $value = null): Builder {
            return $this->whereHasIn($relation, function ($query) use ($column, $operator, $value) {
                if ($column instanceof Closure) {
                    $column($query);
                } else {
                    $query->where($column, $operator, $value);
                }
            });
        };
    }

    /**
     * Add an "or where" clause to a relationship query.
     *
     * @return Closure
     */
    public function orWhereRelationIn(): Closure
    {
        return function ($relation, $column, $operator = null, $value = null): Builder {
            return $this->orWhereHasIn($relation, function ($query) use ($column, $operator, $value) {
                if ($column instanceof Closure) {
                    $column($query);
                } else {
                    $query->where($column, $operator, $value);
                }
            });
        };
    }

    /**
     * Add a polymorphic relationship condition to the query with a where clause.
     *
     * @return Closure
     */
    public function whereMorphRelationIn(): Closure
    {
        return function ($relation, $types, $column, $operator = null, $value = null): Builder {
            return $this->whereHasMorphIn($relation, $types, function ($query) use ($column, $operator, $value) {
                $query->where($column, $operator, $value);
            });
        };
    }

    /**
     * Add a polymorphic relationship condition to the query with an "or where" clause.
     *
     * @return Closure
     */
    public function orWhereMorphRelationIn(): Closure
    {
        return function ($relation, $types, $column, $operator = null, $value = null): Builder {
            return $this->orWhereHasMorphIn($relation, $types, function ($query) use ($column, $operator, $value) {
                $query->where($column, $operator, $value);
            });
        };
    }

    /**
     * Add the "hasin" condition whereIn clause to the query.
     *
     * @return Closure
     */
    protected function addHasInWhere(): Closure
    {
        return function (Builder $hasInQuery, Relation $relation, $operator, $count, $boolean): Builder {
            /** @var Builder $this */
            $hasInQuery->mergeConstraintsFrom($relation->getQuery());

            return $this->canUseExistsForExistenceCheck($operator, $count)
                ? $this->whereIn($relation->getRelationWhereInKey(), $hasInQuery->toBase(), $boolean, $operator === '<' && $count === 1)
                : $this->addWhereCountQuery($hasInQuery->toBase(), $operator, $count, $boolean);
        };
    }
}


================================================
FILE: src/Database/Eloquent/RelationMixin.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Database\Eloquent;

use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrManyThrough;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use LogicException;

class RelationMixin
{
    public function getRelationExistenceInQuery(): Closure
    {
        return function (Builder $query, Builder $parentQuery, $columns = ['*']): Builder {
            $relation = function (Builder $query, Builder $parentQuery, $columns = ['*']): Builder {
                return $query->select($columns);
            };
            // basic builder
            $belongsTo = function (Builder $query, Builder $parentQuery) use ($relation): Builder {
                $columns = $query->qualifyColumn($this->ownerKey);

                $relationQuery = $relation($query, $parentQuery, $columns);

                if ($parentQuery->getQuery()->from == $query->getQuery()->from) {
                    $relationQuery->from(
                        $query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash()
                    );

                    $relationQuery->getModel()->setTable($hash);
                }

                return $relationQuery;
            };
            $belongsToMany = function (Builder $query, Builder $parentQuery) use ($relation): Builder {
                $columns = $this->getExistenceCompareKey();
                if ($parentQuery->getQuery()->from == $query->getQuery()->from) {
                    $query->select($columns);

                    $query->from($this->related->getTable().' as '.$hash = $this->getRelationCountHash());

                    $this->related->setTable($hash);
                }

                $this->performJoin($query);

                return $relation($query, $parentQuery, $columns);
            };
            $hasOneOrMany = function (Builder $query, Builder $parentQuery) use ($relation): Builder {
                $columns = $this->getExistenceCompareKey();
                if ($query->getQuery()->from == $parentQuery->getQuery()->from) {
                    $query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());

                    $query->getModel()->setTable($hash);
                }

                return $relation($query, $parentQuery, $columns);
            };
            $hasOneOrManyThrough = function (Builder $query, Builder $parentQuery) use ($relation): Builder {
                $columns = $this->getQualifiedFirstKeyName();
                if ($parentQuery->getQuery()->from === $query->getQuery()->from) {
                    $query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());

                    $query->join($this->throughParent->getTable(), $this->getQualifiedParentKeyName(), '=', $hash.'.'.$this->secondKey);

                    if ($this->throughParentSoftDeletes()) {
                        $query->whereNull($this->throughParent->getQualifiedDeletedAtColumn());
                    }

                    $query->getModel()->setTable($hash);

                    return $relation($query, $parentQuery, $columns);
                }

                if ($parentQuery->getQuery()->from === $this->throughParent->getTable()) {
                    $table = $this->throughParent->getTable().' as '.$hash = $this->getRelationCountHash();

                    $query->join($table, $hash.'.'.$this->secondLocalKey, '=', $this->getQualifiedFarKeyName());

                    if ($this->throughParentSoftDeletes()) {
                        $query->whereNull($hash.'.'.$this->throughParent->getDeletedAtColumn());
                    }

                    return $relation($query, $parentQuery, $columns);
                }

                $this->performJoin($query);

                return $relation($query, $parentQuery, $columns);
            };
            // extended builder
            $hasOne = function (Builder $query, Builder $parentQuery) use ($hasOneOrMany): Builder {
                if ($this->isOneOfMany()) {
                    $this->mergeOneOfManyJoinsTo($query);
                }

                return $hasOneOrMany($query, $parentQuery);
            };
            $morphOneOrMany = function (Builder $query, Builder $parentQuery) use ($hasOneOrMany): Builder {
                return $hasOneOrMany($query, $parentQuery)->where(
                    $query->qualifyColumn($this->getMorphType()),
                    $this->morphClass
                );
            };
            $morphOne = function (Builder $query, Builder $parentQuery) use ($morphOneOrMany): Builder {
                if ($this->isOneOfMany()) {
                    $this->mergeOneOfManyJoinsTo($query);
                }

                return $morphOneOrMany($query, $parentQuery);
            };
            $morphToMany = function (Builder $query, Builder $parentQuery) use ($belongsToMany): Builder {
                return $belongsToMany($query, $parentQuery)->where(
                    $this->qualifyPivotColumn($this->morphType),
                    $this->morphClass
                );
            };

            return match (true) {
                // extended relation
                $this instanceof HasOne => $hasOne($query, $parentQuery),
                $this instanceof MorphOne => $morphOne($query, $parentQuery),
                $this instanceof MorphOneOrMany => $morphOneOrMany($query, $parentQuery),
                $this instanceof MorphToMany => $morphToMany($query, $parentQuery),
                // basic relation
                $this instanceof BelongsTo => $belongsTo($query, $parentQuery),
                $this instanceof BelongsToMany => $belongsToMany($query, $parentQuery),
                $this instanceof HasOneOrMany => $hasOneOrMany($query, $parentQuery),
                $this instanceof HasOneOrManyThrough => $hasOneOrManyThrough($query, $parentQuery),
                default => throw new LogicException(
                    sprintf('%s must be a relationship instance.', $this::class)
                )
            };
        };
    }

    public function getRelationWhereInKey(): Closure
    {
        return fn (): string => match (true) {
            $this instanceof BelongsTo => $this->getQualifiedForeignKeyName(),
            $this instanceof HasOneOrMany, $this instanceof BelongsToMany => $this->getQualifiedParentKeyName(),
            $this instanceof HasOneOrManyThrough => $this->getQualifiedLocalKeyName(),
            default => throw new LogicException(
                sprintf('%s must be a relationship instance.', $this::class)
            )
        };
    }
}


================================================
FILE: src/HasinServiceProvider.php
================================================
<?php

namespace BiiiiiigMonster\Hasin;

use BiiiiiigMonster\Hasin\Database\Eloquent\BuilderMixin;
use BiiiiiigMonster\Hasin\Database\Eloquent\RelationMixin;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\ServiceProvider;

class HasinServiceProvider extends ServiceProvider
{
    /**
     * @throws \ReflectionException
     */
    public function register()
    {
        // Eloquent\Builder mixin, provides hasin series implementation.
        Builder::mixin(new BuilderMixin());
        // Eloquent\Relation mixin, support for the bottom layer of hasin.
        Relation::mixin(new RelationMixin());
    }
}


================================================
FILE: tests/Features/DoesntHaveInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\User;

test('doesntHaveIn same as doesntHave', function () {
    $doesntHave = User::doesntHave('posts')->orderBy('id')->pluck('id');
    $doesntHaveIn = User::doesntHaveIn('posts')->orderBy('id')->pluck('id');

    expect($doesntHave)->toEqual($doesntHaveIn);
});

test('nested doesntHaveIn same as nested doesntHave', function () {
    $doesntHave = User::doesntHave('posts.comments')->orderBy('id')->pluck('id');
    $doesntHaveIn = User::doesntHaveIn('posts.comments')->orderBy('id')->pluck('id');

    expect($doesntHave)->toEqual($doesntHaveIn);
});


================================================
FILE: tests/Features/DoesntHaveMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('doesntHaveMorphIn same as doesntHaveMorph', function () {
    $doesntHaveMorph = Comment::doesntHaveMorph('commentable', [Post::class])->orderBy('id')->pluck('id');
    $doesntHaveMorphIn = Comment::doesntHaveMorphIn('commentable', [Post::class])->orderBy('id')->pluck('id');

    expect($doesntHaveMorph)->toEqual($doesntHaveMorphIn);
});


================================================
FILE: tests/Features/HasInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Country;
use BiiiiiigMonster\Hasin\Tests\Models\Image;
use BiiiiiigMonster\Hasin\Tests\Models\Supplier;
use BiiiiiigMonster\Hasin\Tests\Models\User;
use BiiiiiigMonster\Hasin\Tests\Models\Video;

test('HasMany: hasIn same as has', function () {
    $has = User::has('posts')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('posts')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('HasOne: hasIn same as has', function () {
    $has = User::has('phone')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('phone')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('BelongsTo: hasIn same as has', function () {
    $has = User::has('country')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('country')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('BelongsToMany: hasIn same as has', function () {
    $has = User::has('roles')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('roles')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('HasOneThrough: hasIn same as has', function () {
    $has = Supplier::has('userHistory')->orderBy('id')->pluck('id');
    $hasIn = Supplier::hasIn('userHistory')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('HasManyThrough: hasIn same as has', function () {
    $has = Country::has('posts')->orderBy('id')->pluck('id');
    $hasIn = Country::hasIn('posts')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('MorphOne: hasIn same as has', function () {
    $has = User::has('image')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('image')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('MorphTo: hasIn same as has', function () {
    $has = Image::has('imageable')->orderBy('id')->pluck('id');
    $hasIn = Image::hasIn('imageable')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('MorphMany: hasIn same as has', function () {
    $has = Video::has('comments')->orderBy('id')->pluck('id');
    $hasIn = Video::hasIn('comments')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('MorphToMany: hasIn same as has', function () {
    $has = Video::has('tags')->orderBy('id')->pluck('id');
    $hasIn = Video::hasIn('tags')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('hasIn(gte 2) same as has(gte 2)', function () {
    $has = User::has('posts', '>=', 2)->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('posts', '>=', 2)->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('nested hasIn same as nested has', function () {
    $has = User::has('posts.comments')->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('posts.comments')->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});

test('nested hasIn(gte 2) same as nested has(gte 2)', function () {
    $has = User::has('posts.comments', '>=', 2)->orderBy('id')->pluck('id');
    $hasIn = User::hasIn('posts.comments', '>=', 2)->orderBy('id')->pluck('id');

    expect($has)->toEqual($hasIn);
});


================================================
FILE: tests/Features/HasMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('hasMorphIn same as hasMorph', function () {
    $hasMorph = Comment::hasMorph('commentable', [Post::class])->orderBy('id')->pluck('id');
    $hasMorphIn = Comment::hasMorphIn('commentable', [Post::class])->orderBy('id')->pluck('id');

    expect($hasMorph)->toEqual($hasMorphIn);
});

test('hasMorphIn(gte 2) same as hasMorph(gte 2)', function () {
    $hasMorph = Comment::hasMorph('commentable', [Post::class], '>=', 2)->orderBy('id')->pluck('id');
    $hasMorphIn = Comment::hasMorphIn('commentable', [Post::class], '>=', 2)->orderBy('id')->pluck('id');

    expect($hasMorph)->toEqual($hasMorphIn);
});


================================================
FILE: tests/Features/OrDoesntHaveInTest.php
================================================
<?php


use BiiiiiigMonster\Hasin\Tests\Models\User;

test('orDoesntHaveIn same as orDoesntHave', function () {
    $orDoesntHave = User::where('age', '>', 18)->orDoesntHave('posts')->orderBy('id')->pluck('id');
    $orDoesntHaveIn = User::where('age', '>', 18)->orDoesntHaveIn('posts')->orderBy('id')->pluck('id');

    expect($orDoesntHave)->toEqual($orDoesntHaveIn);
});

test('nested orDoesntHaveIn same as nested orDoesntHave', function () {
    $orDoesntHave = User::where('age', '>', 18)->orDoesntHave('posts.comments')->orderBy('id')->pluck('id');
    $orDoesntHaveIn = User::where('age', '>', 18)->orDoesntHaveIn('posts.comments')->orderBy('id')->pluck('id');

    expect($orDoesntHave)->toEqual($orDoesntHaveIn);
});


================================================
FILE: tests/Features/OrDoesntHaveMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('orDoesntHaveMorphIn same as orDoesntHaveMorph', function () {
    $orDoesntHaveMorph = Comment::where('status', '>', 2)->orDoesntHaveMorph('commentable', [Post::class])->orderBy('id')->pluck('id');
    $orDoesntHaveMorphIn = Comment::where('status', '>', 2)->orDoesntHaveMorphIn('commentable', [Post::class])->orderBy('id')->pluck('id');

    expect($orDoesntHaveMorph)->toEqual($orDoesntHaveMorphIn);
});


================================================
FILE: tests/Features/OrHasInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\User;

test('orHasIn same as orHas', function () {
    $orHas = User::where('age', '>', 18)->orHas('posts')->orderBy('id')->pluck('id');
    $orHasIn = User::where('age', '>', 18)->orHasIn('posts')->orderBy('id')->pluck('id');

    expect($orHas)->toEqual($orHasIn);
});

test('orHasIn(gte 2) same as orHas(gte 2)', function () {
    $orHas = User::where('age', '>', 18)->orHas('posts', '>=', 2)->orderBy('id')->pluck('id');
    $orHasIn = User::where('age', '>', 18)->orHasIn('posts', '>=', 2)->orderBy('id')->pluck('id');

    expect($orHas)->toEqual($orHasIn);
});

test('nested orHasIn same as nested orHas', function () {
    $orHas = User::where('age', '>', 18)->orHas('posts.comments')->orderBy('id')->pluck('id');
    $orHasIn = User::where('age', '>', 18)->orHasIn('posts.comments')->orderBy('id')->pluck('id');

    expect($orHas)->toEqual($orHasIn);
});

test('nested orHasIn(gte 2) same as nested orHas(gte 2)', function () {
    $orHas = User::where('age', '>', 18)->orHas('posts.comments', '>=', 2)->orderBy('id')->pluck('id');
    $orHasIn = User::where('age', '>', 18)->orHasIn('posts.comments', '>=', 2)->orderBy('id')->pluck('id');

    expect($orHas)->toEqual($orHasIn);
});


================================================
FILE: tests/Features/OrHasMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('orHasMorphIn same as orHasMorph', function () {
    $orHasMorph = Comment::where('status', '>', 2)->orHasMorph('commentable', [Post::class])->orderBy('id')->pluck('id');
    $orHasMorphIn = Comment::where('status', '>', 2)->orHasMorphIn('commentable', [Post::class])->orderBy('id')->pluck('id');

    expect($orHasMorph)->toEqual($orHasMorphIn);
});

test('orHasMorphIn(gte 2) same as orHasMorph(gte 2)', function () {
    $orHasMorph = Comment::where('status', '>', 2)->orHasMorph('commentable', [Post::class], '>=', 2)->orderBy('id')->pluck('id');
    $orHasMorphIn = Comment::where('status', '>', 2)->orHasMorphIn('commentable', [Post::class], '>=', 2)->orderBy('id')->pluck('id');

    expect($orHasMorph)->toEqual($orHasMorphIn);
});


================================================
FILE: tests/Features/OrWhereDoesntHaveInTest.php
================================================
<?php


use BiiiiiigMonster\Hasin\Tests\Models\User;

test('orWhereDoesntHaveIn same as orWhereDoesntHave', function () {
    $orWhereDoesntHave = User::where('age', '>', 18)->orWhereDoesntHave('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');
    $orWhereDoesntHaveIn = User::where('age', '>', 18)->orWhereDoesntHaveIn('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');

    expect($orWhereDoesntHave)->toEqual($orWhereDoesntHaveIn);
});

test('nested orWhereDoesntHaveIn same as nested orWhereDoesntHave', function () {
    $orWhereDoesntHave = User::where('age', '>', 18)->orWhereDoesntHave('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');
    $orWhereDoesntHaveIn = User::where('age', '>', 18)->orWhereDoesntHaveIn('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');

    expect($orWhereDoesntHave)->toEqual($orWhereDoesntHaveIn);
});


================================================
FILE: tests/Features/OrWhereDoesntHaveMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('orWhereDoesntHaveMorphIn same as orWhereDoesntHaveMorph', function () {
    $orWhereDoesntHaveMorph = Comment::where('status', '>', 2)->orWhereDoesntHaveMorph('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');
    $orWhereDoesntHaveMorphIn = Comment::where('status', '>', 2)->orWhereDoesntHaveMorphIn('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');

    expect($orWhereDoesntHaveMorph)->toEqual($orWhereDoesntHaveMorphIn);
});


================================================
FILE: tests/Features/OrWhereHasInTest.php
================================================
<?php


use BiiiiiigMonster\Hasin\Tests\Models\User;

test('orWhereHasIn same as orWhereHas', function () {
    $orWhereHas = User::where('age', '>', 18)->orWhereHas('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');
    $orWhereHasIn = User::where('age', '>', 18)->orWhereHasIn('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');

    expect($orWhereHas)->toEqual($orWhereHasIn);
});

test('nested orWhereHasIn same as nested orWhereHas', function () {
    $orWhereHas = User::where('age', '>', 18)->orWhereHas('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');
    $orWhereHasIn = User::where('age', '>', 18)->orWhereHasIn('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');

    expect($orWhereHas)->toEqual($orWhereHasIn);
});


================================================
FILE: tests/Features/OrWhereHasMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('orWhereHasMorphIn same as orWhereHasMorph', function () {
    $orWhereHasMorph = Comment::where('status', '>', 2)->orWhereHasMorph('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');
    $orWhereHasMorphIn = Comment::where('status', '>', 2)->orWhereHasMorphIn('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');

    expect($orWhereHasMorph)->toEqual($orWhereHasMorphIn);
});


================================================
FILE: tests/Features/OrWhereMorphRelationInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('orWhereMorphRelationIn same as orWhereMorphRelationIn', function () {
    $orWhereMorphRelation = Comment::where('status', '>=', 2)
        ->orWhereMorphRelation('commentable', [Post::class], 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');
    $orWhereMorphRelationIn = Comment::where('status', '>=', 2)
        ->orWhereMorphRelationIn('commentable', [Post::class], 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');

    expect($orWhereMorphRelation)->toEqual($orWhereMorphRelationIn);
});


================================================
FILE: tests/Features/OrWhereRelationInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\User;

test('orWhereRelationIn same as orWhereRelation', function () {
    $orWhereRelation = User::where('age', '>', 18)
        ->orWhereRelation('posts', 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');
    $orWhereRelationIn = User::where('age', '>', 18)
        ->orWhereRelationIn('posts', 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');

    expect($orWhereRelation)->toEqual($orWhereRelationIn);
});

test('nested whereRelationIn same as nested whereRelation', function () {
    $orWhereRelation = User::where('age', '>', 18)
        ->orWhereRelation('posts.comments', 'status', '>=', '2')
        ->orderBy('id')->pluck('id');
    $orWhereRelationIn = User::where('age', '>', 18)
        ->orWhereRelationIn('posts.comments', 'status', '>=', '2')
        ->orderBy('id')->pluck('id');

    expect($orWhereRelation)->toEqual($orWhereRelationIn);
});


================================================
FILE: tests/Features/WhereDoesntHaveInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\User;

test('whereDoesntHaveIn same as whereDoesntHave', function () {
    $whereDoesntHave = User::whereDoesntHave('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');
    $whereDoesntHaveIn = User::whereDoesntHaveIn('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');

    expect($whereDoesntHave)->toEqual($whereDoesntHaveIn);
});

test('nested whereDoesntHaveIn same as nested whereDoesntHave', function () {
    $whereDoesntHave = User::whereDoesntHave('posts.comments', function ($query) {
        $query->where('status', '>', 2);
        ;
    })->orderBy('id')->pluck('id');
    $whereDoesntHaveIn = User::whereDoesntHaveIn('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');

    expect($whereDoesntHave)->toEqual($whereDoesntHaveIn);
});


================================================
FILE: tests/Features/WhereDoesntHaveMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('whereDoesntHaveMorphIn same as whereDoesntHaveMorph', function () {
    $whereDoesntHaveMorph = Comment::whereDoesntHaveMorph('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');
    $whereDoesntHaveMorphIn = Comment::whereDoesntHaveMorphIn('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');

    expect($whereDoesntHaveMorph)->toEqual($whereDoesntHaveMorphIn);
});


================================================
FILE: tests/Features/WhereHasInTest.php
================================================
<?php


use BiiiiiigMonster\Hasin\Tests\Models\User;

test('whereHasIn same as whereHas', function () {
    $whereHas = User::whereHas('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');
    $whereHasIn = User::whereHasIn('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->pluck('id');

    expect($whereHas)->toEqual($whereHasIn);
});

test('nested whereHasIn same as nested whereHas', function () {
    $whereHas = User::whereHas('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');
    $whereHasIn = User::whereHasIn('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->pluck('id');

    expect($whereHas)->toEqual($whereHasIn);
});


================================================
FILE: tests/Features/WhereHasMorphInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('whereHasMorphIn same as whereHasMorph', function () {
    $whereHasMorph = Comment::whereHasMorph('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');
    $whereHasMorphIn = Comment::whereHasMorphIn('commentable', [Post::class], function ($query) {
        $query->where('title', 'like', '%code%');
    })->orderBy('id')->pluck('id');

    expect($whereHasMorph)->toEqual($whereHasMorphIn);
});


================================================
FILE: tests/Features/WhereMorphRelationInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Post;

test('whereMorphRelationIn same as whereMorphRelation', function () {
    $whereMorphRelation = Comment::whereMorphRelation('commentable', [Post::class], 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');
    $whereMorphRelationIn = Comment::whereMorphRelationIn('commentable', [Post::class], 'title', 'like', '%code%')
        ->orderBy('id')->pluck('id');

    expect($whereMorphRelation)->toEqual($whereMorphRelationIn);
});


================================================
FILE: tests/Features/WhereRelationInTest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\Models\User;

test('whereRelationIn same as whereRelation', function () {
    $whereRelation = User::whereRelation('posts', 'title', 'like', '%code%')->orderBy('id')->pluck('id');
    $whereRelationIn = User::whereRelationIn('posts', 'title', 'like', '%code%')->orderBy('id')->pluck('id');

    expect($whereRelation)->toEqual($whereRelationIn);
});

test('nested whereRelationIn same as nested whereRelation', function () {
    $whereRelation = User::whereRelation('posts.comments', 'status', '>=', '2')->orderBy('id')->pluck('id');
    $whereRelationIn = User::whereRelationIn('posts.comments', 'status', '>=', '2')->orderBy('id')->pluck('id');

    expect($whereRelation)->toEqual($whereRelationIn);
});


================================================
FILE: tests/Features/WithWhereHasInTest.php
================================================
<?php


use BiiiiiigMonster\Hasin\Tests\Models\User;

test('withWhereHasIn same as withWhereHas', function () {
    $whereHas = User::withWhereHas('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->get();
    $whereHasIn = User::withWhereHasIn('posts', function ($query) {
        $query->where('votes', '>', 20);
    })->orderBy('id')->get();

    expect($whereHas->pluck('id'))->toEqual($whereHasIn->pluck('id'))
        ->and($whereHas->pluck('posts.id'))->toEqual($whereHasIn->pluck('posts.id'));
});

test('nested withWhereHasIn same as nested withWhereHas', function () {
    $whereHas = User::withWhereHas('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->get();
    $whereHasIn = User::withWhereHasIn('posts.comments', function ($query) {
        $query->where('status', '>', 2);
    })->orderBy('id')->get();

    expect($whereHas->pluck('id'))->toEqual($whereHasIn->pluck('id'))
        ->and($whereHas->pluck('posts.id'))->toEqual($whereHasIn->pluck('posts.id'))
        ->and($whereHas->pluck('posts.comments.id'))->toEqual($whereHasIn->pluck('posts.comments.id'));
});


================================================
FILE: tests/Models/Comment.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Comment extends Model
{
    use HasFactory;

    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}


================================================
FILE: tests/Models/Country.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Country extends Model
{
    use HasFactory;

    public function posts(): HasManyThrough
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}


================================================
FILE: tests/Models/History.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class History extends Model
{
    use HasFactory;
}


================================================
FILE: tests/Models/Image.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class Image extends Model
{
    use HasFactory;

    public function imageable(): MorphTo
    {
        return $this->morphTo();
    }
}


================================================
FILE: tests/Models/Phone.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
    use HasFactory;
}


================================================
FILE: tests/Models/Post.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Post extends Model
{
    use HasFactory;

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function image(): MorphOne
    {
        return $this->morphOne(Image::class, 'imageable');
    }

    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }

    public function tags(): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable')->using(Taggable::class);
    }
}


================================================
FILE: tests/Models/Role.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Role extends Model
{
    use HasFactory;

    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class)->using(RoleUser::class)->withTimestamps();
    }
}


================================================
FILE: tests/Models/RoleUser.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\Pivot;

class RoleUser extends Pivot
{
    use HasFactory;
}


================================================
FILE: tests/Models/Supplier.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;

class Supplier extends Model
{
    use HasFactory;

    public function userHistory(): HasOneThrough
    {
        return $this->hasOneThrough(History::class, User::class);
    }
}


================================================
FILE: tests/Models/Tag.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Tag extends Model
{
    use HasFactory;

    public function posts(): MorphToMany
    {
        return $this->morphToMany(Post::class, 'taggable')->using(Taggable::class);
    }

    public function videos(): MorphToMany
    {
        return $this->morphToMany(Video::class, 'taggable')->using(Taggable::class);
    }
}


================================================
FILE: tests/Models/Taggable.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\MorphPivot;

class Taggable extends MorphPivot
{
    use HasFactory;
}


================================================
FILE: tests/Models/User.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphOne;

class User extends Model
{
    use HasFactory;

    public function country(): BelongsTo
    {
        return $this->belongsTo(Country::class);
    }

    public function supplier(): BelongsTo
    {
        return $this->belongsTo(Supplier::class);
    }

    public function phone(): HasOne
    {
        return $this->hasOne(Phone::class);
    }

    public function history(): HasOne
    {
        return $this->hasOne(History::class);
    }

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class)->using(RoleUser::class)->withTimestamps();
    }

    public function image(): MorphOne
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}


================================================
FILE: tests/Models/Video.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;

class Video extends Model
{
    use HasFactory;

    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }

    public function tags(): MorphToMany
    {
        return $this->morphToMany(Tag::class, 'taggable')->using(Taggable::class);
    }
}


================================================
FILE: tests/Pest.php
================================================
<?php

use BiiiiiigMonster\Hasin\Tests\TestCase;

uses(TestCase::class)->in(__DIR__);


================================================
FILE: tests/TestCase.php
================================================
<?php

namespace BiiiiiigMonster\Hasin\Tests;

use BiiiiiigMonster\Hasin\HasinServiceProvider;
use BiiiiiigMonster\Hasin\Tests\Models\Comment;
use BiiiiiigMonster\Hasin\Tests\Models\Country;
use BiiiiiigMonster\Hasin\Tests\Models\History;
use BiiiiiigMonster\Hasin\Tests\Models\Image;
use BiiiiiigMonster\Hasin\Tests\Models\Phone;
use BiiiiiigMonster\Hasin\Tests\Models\Post;
use BiiiiiigMonster\Hasin\Tests\Models\Role;
use BiiiiiigMonster\Hasin\Tests\Models\Supplier;
use BiiiiiigMonster\Hasin\Tests\Models\Tag;
use BiiiiiigMonster\Hasin\Tests\Models\User;
use BiiiiiigMonster\Hasin\Tests\Models\Video;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
use Orchestra\Testbench\TestCase as Orchestra;

class TestCase extends Orchestra
{
    private Migration $migration;

    protected function getPackageProviders($app)
    {
        return [
            HasinServiceProvider::class,
        ];
    }

    protected function defineDatabaseMigrations()
    {
        $this->migration->up();
    }

    protected function destroyDatabaseMigrations()
    {
        $this->migration->down();
    }

    protected function defineDatabaseSeeders()
    {
        $tags = Tag::factory(20)->create();
        $countries = Country::factory(15)->create();
        $suppliers = Supplier::factory(15)->create();
        $roles = Role::factory(10)->create();

        $users = User::factory(15)
            ->has(History::factory())
            ->has(Phone::factory())
            ->has(Image::factory(3))
            ->hasAttached($roles->random(5))
            ->sequence(fn () => ['country_id' => $countries->pluck('id')->random()])
            ->sequence(fn () => ['supplier_id' => $suppliers->pluck('id')->random()])
            ->create();

        $posts = Post::factory(15)
            ->sequence(fn () => ['user_id' => $users->pluck('id')->random()])
            ->hasAttached($tags->random(15))
            ->create();

        $videos = Video::factory(15)->hasAttached($tags->random(15))->create();

        $posts->random(5)->map(function ($post) {
            Comment::factory(3)->for($post, 'commentable')->create();
            Image::factory(2)->for($post, 'imageable')->create();
        });

        $videos->random(5)->map(function ($video) {
            Comment::factory(3)->for($video, 'commentable')->create();
        });
    }

    public function getEnvironmentSetUp($app)
    {
        config()->set('database.connections.mysql.prefix', 'hasin_test_');

        Schema::defaultStringLength(191);
        Factory::guessFactoryNamesUsing(
            fn (string $modelName) => 'BiiiiiigMonster\\Hasin\\Database\\Factories\\'.class_basename($modelName).'Factory'
        );

        $this->migration = include __DIR__.'/../database/migrations/create_hasin_test_table.php';
    }
}
Download .txt
gitextract_znsrf2cn/

├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── config.yml
│   ├── dependabot.yml
│   └── workflows/
│       ├── dependabot-auto-merge.yml
│       ├── fix-php-code-style-issues.yml
│       └── run-tests.yml
├── .gitignore
├── .scrutinizer.yml
├── CHANGELOG.md
├── LICENSE
├── README-CN.md
├── README.md
├── _laravel_ide_helper.php
├── composer.json
├── database/
│   ├── factories/
│   │   ├── CommentFactory.php
│   │   ├── CountryFactory.php
│   │   ├── HistoryFactory.php
│   │   ├── ImageFactory.php
│   │   ├── PhoneFactory.php
│   │   ├── PostFactory.php
│   │   ├── RoleFactory.php
│   │   ├── SupplierFactory.php
│   │   ├── TagFactory.php
│   │   ├── UserFactory.php
│   │   └── VideoFactory.php
│   └── migrations/
│       └── create_hasin_test_table.php
├── phpunit.xml.dist
├── pint.json
├── src/
│   ├── Database/
│   │   └── Eloquent/
│   │       ├── BuilderMixin.php
│   │       └── RelationMixin.php
│   └── HasinServiceProvider.php
└── tests/
    ├── Features/
    │   ├── DoesntHaveInTest.php
    │   ├── DoesntHaveMorphInTest.php
    │   ├── HasInTest.php
    │   ├── HasMorphInTest.php
    │   ├── OrDoesntHaveInTest.php
    │   ├── OrDoesntHaveMorphInTest.php
    │   ├── OrHasInTest.php
    │   ├── OrHasMorphInTest.php
    │   ├── OrWhereDoesntHaveInTest.php
    │   ├── OrWhereDoesntHaveMorphInTest.php
    │   ├── OrWhereHasInTest.php
    │   ├── OrWhereHasMorphInTest.php
    │   ├── OrWhereMorphRelationInTest.php
    │   ├── OrWhereRelationInTest.php
    │   ├── WhereDoesntHaveInTest.php
    │   ├── WhereDoesntHaveMorphInTest.php
    │   ├── WhereHasInTest.php
    │   ├── WhereHasMorphInTest.php
    │   ├── WhereMorphRelationInTest.php
    │   ├── WhereRelationInTest.php
    │   └── WithWhereHasInTest.php
    ├── Models/
    │   ├── Comment.php
    │   ├── Country.php
    │   ├── History.php
    │   ├── Image.php
    │   ├── Phone.php
    │   ├── Post.php
    │   ├── Role.php
    │   ├── RoleUser.php
    │   ├── Supplier.php
    │   ├── Tag.php
    │   ├── Taggable.php
    │   ├── User.php
    │   └── Video.php
    ├── Pest.php
    └── TestCase.php
Download .txt
SYMBOL INDEX (113 symbols across 30 files)

FILE: _laravel_ide_helper.php
  class Builder (line 8) | class Builder
    method hasIn (line 24) | public function hasIn($relation, $operator = '>=', $count = 1, $boolea...
    method orHasIn (line 39) | public function orHasIn($relation, $operator = '>=', $count = 1)
    method doesntHaveIn (line 54) | public function doesntHaveIn($relation, $boolean = 'and', Closure $cal...
    method orDoesntHaveIn (line 66) | public function orDoesntHaveIn()
    method whereHasIn (line 82) | public function whereHasIn($relation, Closure $callback = null, $opera...
    method orWhereHasIn (line 98) | public function orWhereHasIn($relation, Closure $callback = null, $ope...
    method whereDoesntHaveIn (line 112) | public function whereDoesntHaveIn($relation, Closure $callback = null)
    method orWhereDoesntHaveIn (line 126) | public function orWhereDoesntHaveIn($relation, Closure $callback = null)
    method hasMorphIn (line 144) | public function hasMorphIn($relation, $types, $operator = '>=', $count...
    method orHasMorphIn (line 160) | public function orHasMorphIn($relation, $types, $operator = '>=', $cou...
    method doesntHaveMorphIn (line 176) | public function doesntHaveMorphIn($relation, $types, $boolean = 'and',...
    method orDoesntHaveMorphIn (line 190) | public function orDoesntHaveMorphIn($relation, $types)
    method whereHasMorphIn (line 202) | public function whereHasMorphIn()
    method orWhereHasMorphIn (line 219) | public function orWhereHasMorphIn($relation, $types, Closure $callback...
    method whereDoesntHaveMorphIn (line 234) | public function whereDoesntHaveMorphIn($relation, $types, Closure $cal...
    method orWhereDoesntHaveMorphIn (line 249) | public function orWhereDoesntHaveMorphIn($relation, $types, Closure $c...
    method whereRelationIn (line 263) | public function whereRelationIn($relation, $column, $operator = null, ...
    method orWhereRelationIn (line 277) | public function orWhereRelationIn($relation, $column, $operator = null...
    method whereMorphRelationIn (line 292) | public function whereMorphRelationIn($relation, $types, $column, $oper...
    method orWhereMorphRelationIn (line 307) | public function orWhereMorphRelationIn($relation, $types, $column, $op...

FILE: database/factories/CommentFactory.php
  class CommentFactory (line 8) | class CommentFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/CountryFactory.php
  class CountryFactory (line 8) | class CountryFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/HistoryFactory.php
  class HistoryFactory (line 8) | class HistoryFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/ImageFactory.php
  class ImageFactory (line 8) | class ImageFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/PhoneFactory.php
  class PhoneFactory (line 8) | class PhoneFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/PostFactory.php
  class PostFactory (line 8) | class PostFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/RoleFactory.php
  class RoleFactory (line 8) | class RoleFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/SupplierFactory.php
  class SupplierFactory (line 8) | class SupplierFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/TagFactory.php
  class TagFactory (line 8) | class TagFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/UserFactory.php
  class UserFactory (line 8) | class UserFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/factories/VideoFactory.php
  class VideoFactory (line 8) | class VideoFactory extends Factory
    method definition (line 17) | public function definition()

FILE: database/migrations/create_hasin_test_table.php
  method up (line 13) | public function up()
  method down (line 99) | public function down()

FILE: src/Database/Eloquent/BuilderMixin.php
  class BuilderMixin (line 11) | class BuilderMixin
    method hasIn (line 18) | public function hasIn(): Closure
    method hasInNested (line 70) | protected function hasInNested(): Closure
    method orHasIn (line 101) | public function orHasIn(): Closure
    method doesntHaveIn (line 114) | public function doesntHaveIn(): Closure
    method orDoesntHaveIn (line 127) | public function orDoesntHaveIn(): Closure
    method whereHasIn (line 140) | public function whereHasIn(): Closure
    method withWhereHasIn (line 155) | public function withWhereHasIn(): Closure
    method orWhereHasIn (line 169) | public function orWhereHasIn(): Closure
    method whereDoesntHaveIn (line 182) | public function whereDoesntHaveIn(): Closure
    method orWhereDoesntHaveIn (line 195) | public function orWhereDoesntHaveIn(): Closure
    method hasMorphIn (line 208) | public function hasMorphIn(): Closure
    method orHasMorphIn (line 250) | public function orHasMorphIn(): Closure
    method doesntHaveMorphIn (line 263) | public function doesntHaveMorphIn(): Closure
    method orDoesntHaveMorphIn (line 276) | public function orDoesntHaveMorphIn(): Closure
    method whereHasMorphIn (line 289) | public function whereHasMorphIn(): Closure
    method orWhereHasMorphIn (line 302) | public function orWhereHasMorphIn(): Closure
    method whereDoesntHaveMorphIn (line 315) | public function whereDoesntHaveMorphIn(): Closure
    method orWhereDoesntHaveMorphIn (line 328) | public function orWhereDoesntHaveMorphIn(): Closure
    method whereRelationIn (line 341) | public function whereRelationIn(): Closure
    method orWhereRelationIn (line 359) | public function orWhereRelationIn(): Closure
    method whereMorphRelationIn (line 377) | public function whereMorphRelationIn(): Closure
    method orWhereMorphRelationIn (line 391) | public function orWhereMorphRelationIn(): Closure
    method addHasInWhere (line 405) | protected function addHasInWhere(): Closure

FILE: src/Database/Eloquent/RelationMixin.php
  class RelationMixin (line 17) | class RelationMixin
    method getRelationExistenceInQuery (line 19) | public function getRelationExistenceInQuery(): Closure
    method getRelationWhereInKey (line 143) | public function getRelationWhereInKey(): Closure

FILE: src/HasinServiceProvider.php
  class HasinServiceProvider (line 11) | class HasinServiceProvider extends ServiceProvider
    method register (line 16) | public function register()

FILE: tests/Models/Comment.php
  class Comment (line 9) | class Comment extends Model
    method commentable (line 13) | public function commentable(): MorphTo

FILE: tests/Models/Country.php
  class Country (line 9) | class Country extends Model
    method posts (line 13) | public function posts(): HasManyThrough

FILE: tests/Models/History.php
  class History (line 8) | class History extends Model

FILE: tests/Models/Image.php
  class Image (line 9) | class Image extends Model
    method imageable (line 13) | public function imageable(): MorphTo

FILE: tests/Models/Phone.php
  class Phone (line 8) | class Phone extends Model

FILE: tests/Models/Post.php
  class Post (line 12) | class Post extends Model
    method user (line 16) | public function user(): BelongsTo
    method image (line 21) | public function image(): MorphOne
    method comments (line 26) | public function comments(): MorphMany
    method tags (line 31) | public function tags(): MorphToMany

FILE: tests/Models/Role.php
  class Role (line 9) | class Role extends Model
    method users (line 13) | public function users(): BelongsToMany

FILE: tests/Models/RoleUser.php
  class RoleUser (line 8) | class RoleUser extends Pivot

FILE: tests/Models/Supplier.php
  class Supplier (line 9) | class Supplier extends Model
    method userHistory (line 13) | public function userHistory(): HasOneThrough

FILE: tests/Models/Tag.php
  class Tag (line 9) | class Tag extends Model
    method posts (line 13) | public function posts(): MorphToMany
    method videos (line 18) | public function videos(): MorphToMany

FILE: tests/Models/Taggable.php
  class Taggable (line 8) | class Taggable extends MorphPivot

FILE: tests/Models/User.php
  class User (line 13) | class User extends Model
    method country (line 17) | public function country(): BelongsTo
    method supplier (line 22) | public function supplier(): BelongsTo
    method phone (line 27) | public function phone(): HasOne
    method history (line 32) | public function history(): HasOne
    method posts (line 37) | public function posts(): HasMany
    method roles (line 42) | public function roles(): BelongsToMany
    method image (line 47) | public function image(): MorphOne

FILE: tests/Models/Video.php
  class Video (line 10) | class Video extends Model
    method comments (line 14) | public function comments(): MorphMany
    method tags (line 19) | public function tags(): MorphToMany

FILE: tests/TestCase.php
  class TestCase (line 22) | class TestCase extends Orchestra
    method getPackageProviders (line 26) | protected function getPackageProviders($app)
    method defineDatabaseMigrations (line 33) | protected function defineDatabaseMigrations()
    method destroyDatabaseMigrations (line 38) | protected function destroyDatabaseMigrations()
    method defineDatabaseSeeders (line 43) | protected function defineDatabaseSeeders()
    method getEnvironmentSetUp (line 76) | public function getEnvironmentSetUp($app)
Condensed preview — 67 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (99K chars).
[
  {
    "path": ".gitattributes",
    "chars": 807,
    "preview": "# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test and"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 608,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Ask a question\n    url: https://github.com/biiiiiigmonster/hasin/di"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 321,
    "preview": "# Please see the documentation for all configuration options:\n# https://help.github.com/github/administering-a-repositor"
  },
  {
    "path": ".github/workflows/dependabot-auto-merge.yml",
    "chars": 1054,
    "preview": "name: dependabot-auto-merge\non: pull_request_target\n\npermissions:\n  pull-requests: write\n  contents: write\n\njobs:\n  depe"
  },
  {
    "path": ".github/workflows/fix-php-code-style-issues.yml",
    "chars": 449,
    "preview": "name: Fix PHP code style issues\n\non: [push]\n\njobs:\n  php-code-styling:\n    runs-on: ubuntu-latest\n\n    steps:\n      - na"
  },
  {
    "path": ".github/workflows/run-tests.yml",
    "chars": 1711,
    "preview": "name: run-tests\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n\njobs:\n  test:\n  "
  },
  {
    "path": ".gitignore",
    "chars": 124,
    "preview": ".idea\n.phpunit.result.cache\nbuild\ncomposer.lock\ncoverage\ndocs\nphpunit.xml\ntestbench.yaml\nvendor\nnode_modules\n.phpunit.ca"
  },
  {
    "path": ".scrutinizer.yml",
    "chars": 505,
    "preview": "checks:\n  php:\n    code_rating: true\n    remove_extra_empty_lines: true\n    remove_php_closing_tag: true\n    remove_trai"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 77,
    "preview": "# Changelog\n\nAll notable changes to `hasin` will be documented in this file.\n"
  },
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "The MIT License (MIT)\n\nCopyright (c) Yunfeng Lu\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README-CN.md",
    "chars": 4199,
    "preview": "[English](./README.md) | 中文\n\n<div align=\"center\">\n\n# LARAVEL HASIN\n\n[![Latest Version on Packagist](https://img.shields."
  },
  {
    "path": "README.md",
    "chars": 5381,
    "preview": "English | [中文](./README-CN.md)\n\n<div align=\"center\">\n\n# LARAVEL HASIN\n\n[![Latest Version on Packagist](https://img.shiel"
  },
  {
    "path": "_laravel_ide_helper.php",
    "chars": 12261,
    "preview": "<?php\n\nnamespace Illuminate\\Database\\Eloquent\n{\n    use Closure;\n\n    if (false) {\n        class Builder\n        {\n     "
  },
  {
    "path": "composer.json",
    "chars": 1317,
    "preview": "{\n    \"name\": \"biiiiiigmonster/hasin\",\n    \"description\": \"Laravel framework relation has in implement\",\n    \"type\": \"li"
  },
  {
    "path": "database/factories/CommentFactory.php",
    "chars": 508,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse Illumina"
  },
  {
    "path": "database/factories/CountryFactory.php",
    "chars": 444,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Country;\nuse Illumina"
  },
  {
    "path": "database/factories/HistoryFactory.php",
    "chars": 447,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\History;\nuse Illumina"
  },
  {
    "path": "database/factories/ImageFactory.php",
    "chars": 433,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Image;\nuse Illuminate"
  },
  {
    "path": "database/factories/PhoneFactory.php",
    "chars": 450,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Phone;\nuse Illuminate"
  },
  {
    "path": "database/factories/PostFactory.php",
    "chars": 495,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\nuse Illuminate\\"
  },
  {
    "path": "database/factories/RoleFactory.php",
    "chars": 432,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Role;\nuse Illuminate\\"
  },
  {
    "path": "database/factories/SupplierFactory.php",
    "chars": 444,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Supplier;\nuse Illumin"
  },
  {
    "path": "database/factories/TagFactory.php",
    "chars": 429,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Tag;\nuse Illuminate\\D"
  },
  {
    "path": "database/factories/UserFactory.php",
    "chars": 499,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\nuse Illuminate\\"
  },
  {
    "path": "database/factories/VideoFactory.php",
    "chars": 435,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Factories;\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Video;\nuse Illuminate"
  },
  {
    "path": "database/migrations/create_hasin_test_table.php",
    "chars": 3943,
    "preview": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "phpunit.xml.dist",
    "chars": 1398,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:noName"
  },
  {
    "path": "pint.json",
    "chars": 66,
    "preview": "{\n    \"preset\": \"psr12\",\n    \"exclude\": [\n        \"build\"\n    ]\n}\n"
  },
  {
    "path": "src/Database/Eloquent/BuilderMixin.php",
    "chars": 14477,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Eloquent;\n\nuse Closure;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Il"
  },
  {
    "path": "src/Database/Eloquent/RelationMixin.php",
    "chars": 7019,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Database\\Eloquent;\n\nuse Closure;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Il"
  },
  {
    "path": "src/HasinServiceProvider.php",
    "chars": 682,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin;\n\nuse BiiiiiigMonster\\Hasin\\Database\\Eloquent\\BuilderMixin;\nuse BiiiiiigMonster\\H"
  },
  {
    "path": "tests/Features/DoesntHaveInTest.php",
    "chars": 602,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('doesntHaveIn same as doesntHave', function () {\n    $doesntHa"
  },
  {
    "path": "tests/Features/DoesntHaveMorphInTest.php",
    "chars": 447,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('doesntHaveMor"
  },
  {
    "path": "tests/Features/HasInTest.php",
    "chars": 3173,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Country;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Image;\nuse BiiiiiigMonster"
  },
  {
    "path": "tests/Features/HasMorphInTest.php",
    "chars": 714,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('hasMorphIn sa"
  },
  {
    "path": "tests/Features/OrDoesntHaveInTest.php",
    "chars": 727,
    "preview": "<?php\n\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('orDoesntHaveIn same as orDoesntHave', function () {\n    $orD"
  },
  {
    "path": "tests/Features/OrDoesntHaveMorphInTest.php",
    "chars": 513,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('orDoesntHaveM"
  },
  {
    "path": "tests/Features/OrHasInTest.php",
    "chars": 1240,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('orHasIn same as orHas', function () {\n    $orHas = User::wher"
  },
  {
    "path": "tests/Features/OrHasMorphInTest.php",
    "chars": 846,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('orHasMorphIn "
  },
  {
    "path": "tests/Features/OrWhereDoesntHaveInTest.php",
    "chars": 1079,
    "preview": "<?php\n\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('orWhereDoesntHaveIn same as orWhereDoesntHave', function () "
  },
  {
    "path": "tests/Features/OrWhereDoesntHaveMorphInTest.php",
    "chars": 707,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('orWhereDoesnt"
  },
  {
    "path": "tests/Features/OrWhereHasInTest.php",
    "chars": 967,
    "preview": "<?php\n\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('orWhereHasIn same as orWhereHas', function () {\n    $orWhere"
  },
  {
    "path": "tests/Features/OrWhereHasMorphInTest.php",
    "chars": 651,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('orWhereHasMor"
  },
  {
    "path": "tests/Features/OrWhereMorphRelationInTest.php",
    "chars": 631,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('orWhereMorphR"
  },
  {
    "path": "tests/Features/OrWhereRelationInTest.php",
    "chars": 938,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('orWhereRelationIn same as orWhereRelation', function () {\n   "
  },
  {
    "path": "tests/Features/WhereDoesntHaveInTest.php",
    "chars": 964,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('whereDoesntHaveIn same as whereDoesntHave', function () {\n   "
  },
  {
    "path": "tests/Features/WhereDoesntHaveMorphInTest.php",
    "chars": 641,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('whereDoesntHa"
  },
  {
    "path": "tests/Features/WhereHasInTest.php",
    "chars": 843,
    "preview": "<?php\n\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('whereHasIn same as whereHas', function () {\n    $whereHas = "
  },
  {
    "path": "tests/Features/WhereHasMorphInTest.php",
    "chars": 585,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('whereHasMorph"
  },
  {
    "path": "tests/Features/WhereMorphRelationInTest.php",
    "chars": 543,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Comment;\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\Post;\n\ntest('whereMorphRel"
  },
  {
    "path": "tests/Features/WhereRelationInTest.php",
    "chars": 746,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('whereRelationIn same as whereRelation', function () {\n    $wh"
  },
  {
    "path": "tests/Features/WithWhereHasInTest.php",
    "chars": 1176,
    "preview": "<?php\n\n\nuse BiiiiiigMonster\\Hasin\\Tests\\Models\\User;\n\ntest('withWhereHasIn same as withWhereHas', function () {\n    $whe"
  },
  {
    "path": "tests/Models/Comment.php",
    "chars": 343,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Country.php",
    "chars": 382,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/History.php",
    "chars": 202,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Image.php",
    "chars": 339,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Phone.php",
    "chars": 200,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Post.php",
    "chars": 878,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Role.php",
    "chars": 405,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/RoleUser.php",
    "chars": 213,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Supplier.php",
    "chars": 389,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Tag.php",
    "chars": 532,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Taggable.php",
    "chars": 223,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/User.php",
    "chars": 1217,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Models/Video.php",
    "chars": 565,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illumin"
  },
  {
    "path": "tests/Pest.php",
    "chars": 86,
    "preview": "<?php\n\nuse BiiiiiigMonster\\Hasin\\Tests\\TestCase;\n\nuses(TestCase::class)->in(__DIR__);\n"
  },
  {
    "path": "tests/TestCase.php",
    "chars": 2879,
    "preview": "<?php\n\nnamespace BiiiiiigMonster\\Hasin\\Tests;\n\nuse BiiiiiigMonster\\Hasin\\HasinServiceProvider;\nuse BiiiiiigMonster\\Hasin"
  }
]

About this extraction

This page contains the full source code of the biiiiiigmonster/hasin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 67 files (88.0 KB), approximately 24.2k tokens, and a symbol index with 113 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!