[
  {
    "path": ".gitattributes",
    "content": "/.editorconfig      export-ignore\n/.gitattributes     export-ignore\n/.gitignore         export-ignore\n/.github            export-ignore\n/phpunit.xml.dist   export-ignore\n/tests              export-ignore\n/CHANGELOG.md       export-ignore\n/CONTRIBUTING.md    export-ignore\n/README.md          export-ignore"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: Tests\n\non:\n  pull_request:\n  push:\n    branches: [master, main]\n\njobs:\n  test:\n    runs-on: ubuntu-20.04\n    strategy:\n      fail-fast: false\n      matrix:\n        php: [7.2, 7.3, 7.4, 8.0, 8.1]\n        stability: [prefer-lowest, prefer-stable]\n\n    name: PHP ${{ matrix.php }} - ${{ matrix.stability }} Test\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Setup PHP\n        uses: shivammathur/setup-php@v2\n        with:\n          php-version: ${{ matrix.php }}\n          extensions: dom, curl, libxml, mbstring, zip, pdo\n          ini-values: error_reporting=E_ALL\n          tools: composer:v2\n          coverage: none\n\n      - name: Install dependencies\n        uses: nick-invision/retry@v1\n        with:\n          timeout_minutes: 5\n          max_attempts: 5\n          command: composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress\n\n      - name: Run tests\n        run: ./vendor/bin/phpunit\n        vendor/bin/phpunit --verbose"
  },
  {
    "path": ".gitignore",
    "content": "/vendor\ncomposer.lock\n*.cache"
  },
  {
    "path": "README.md",
    "content": "# Laravel Eloquent: Eager Load Pivot Relations\n\nEager load pivot relations for Laravel Eloquent's BelongsToMany relation.  \nMedium Story: https://medium.com/@ajcastro29/laravel-eloquent-eager-load-pivot-relations-dba579f3fd3a\n\n## Installation\n\n```\ncomposer require ajcastro/eager-load-pivot-relations\n```\n\n## Usage and Example\n\nThere are use-cases where in a pivot model has relations to be eager loaded.\nExample, in a procurement system, we have the following:\n\n**Tables**\n\n```\nitems\n - id\n - name\nunits\n - id\n - name (pc, box, etc...)\nplans (annual procurement plan)\n - id\nplan_item (pivot for plans and items)\n - id\n - plan_id\n - item_id\n - unit_id\n```\n\n**Models**\n\n```php\nclass Unit extends \\Eloquent {\n}\nuse AjCastro\\EagerLoadPivotRelations\\EagerLoadPivotTrait;\nclass Item extends \\Eloquent\n{\n    // Use the trait here to override eloquent builder.\n    // It is used in this model because it is the relation model defined in\n    // Plan::items() relation.\n    use EagerLoadPivotTrait;\n    public function plans()\n    {\n        return $this->belongsToMany('Plan', 'plan_item');\n    }\n}\nclass Plan extends \\Eloquent\n{\n    public function items()\n    {\n        return $this->belongsToMany('Item', 'plan_item')\n            ->using('PlanItem')\n            // make sure to include the necessary foreign key in this case the `unit_id`\n            ->withPivot('unit_id', 'qty', 'price');\n    }\n}\n// Pivot model\nclass PlanItem extends \\Illuminate\\Database\\Eloquent\\Relations\\Pivot\n{\n    protected $table = 'plan_item';\n    public function unit()\n    {\n        return $this->belongsTo('Unit');\n    }\n}\n```\n\nFrom the code above, `plans` and `items` has `Many-to-Many` relationship. Each item in a plan has a selected `unit`, unit of measurement.\nIt also possible for other scenario that the pivot model will have other many relations.\n\n## Eager Loading Pivot Relations\n\nUse keyword `pivot` in eager loading pivot models. So from the example above, the pivot model `PlanItem` can eager load the `unit` relation by doing this:\n\n```\nreturn Plan::with('items.pivot.unit')->get();\n```\n\nThe resulting data structure will be:\n\n![image](https://cloud.githubusercontent.com/assets/4918318/17958278/0d3c962a-6acb-11e6-8415-c48d01457cd6.png)\n\nYou may also access other relations for example:\n\n```\nreturn Plan::with([\n  'items.pivot.unit',\n  'items.pivot.unit.someRelation',\n  'items.pivot.anotherRelation',\n  // It is also possible to eager load nested pivot models\n  'items.pivot.unit.someBelongsToManyRelation.pivot.anotherRelationFromAnotherPivot',\n])->get();\n```\n\n## Custom Pivot Accessor\n\nYou can customize the __\"pivot accessor\"__, so instead of using the keyword `pivot`, we can declare it as `planItem`.\nJust chain the `as()` method in the definition of the `BelongsToMany` relation.\n\n```php\nclass Plan extends \\Eloquent\n{\n    public function items()\n    {\n        return $this->belongsToMany('Item', 'plan_item')\n            ->withPivot('unit_id', 'qty', 'price')\n            ->using('PlanItem')\n            ->as('planItem');\n    }\n}\n```\n\nMake sure we also use the trait\nto our main model which is the `Plan` model, because the package needs to acess \nthe belongsToMany relation (`items` relation) to recognize the used pivot acessor.\n\n```php\nuse AjCastro\\EagerLoadPivotRelations\\EagerLoadPivotTrait;\nclass Plan extends \\Eloquent\n{\n    use EagerLoadPivotTrait;\n}\n```\n\nSo instead of using `pivot`, we can eager load it by defined pivot accessor `planItem`.\n\n```php\nreturn Plan::with('items.planItem.unit')->get();\n```\n```php\n$plan = Plan::with('items.planItem.unit');\nforeach ($plan->items as $item) {\n    $unit = $item->planItem->unit;\n    echo $unit->name;\n}\n```\n\n## Other Examples and Use-cases\nhttps://github.com/ajcastro/eager-load-pivot-relations-examples\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"ajcastro/eager-load-pivot-relations\",\n    \"description\": \"Eager load pivot relations for Laravel Eloquent's BelongsToMany relation.\",\n    \"type\": \"library\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Arjon Jason Castro\",\n            \"email\": \"ajcastro29@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=5.6.0\"\n    },\n    \"require-dev\": {\n        \"laravel/framework\": \">= 5.0.0\",\n        \"laravel/legacy-factories\": \">= 1.0.0\",\n        \"orchestra/testbench\": \">= 3.0.0\",\n        \"phpunit/phpunit\": \">= 6.0.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"AjCastro\\\\EagerLoadPivotRelations\\\\\": \"src\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"AjCastro\\\\EagerLoadPivotRelations\\\\Tests\\\\\": \"tests\"\n        },\n        \"classmap\": [\n            \"tests/Database/Migrations\"\n        ]\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n            ],\n            \"aliases\": {\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         bootstrap=\"./vendor/autoload.php\"\n         colors=\"true\"\n         verbose=\"true\"\n         xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/9.5/phpunit.xsd\"\n>\n    <testsuites>\n        <testsuite name=\"Unit\">\n            <directory suffix=\"Test.php\">./tests/Unit</directory>\n        </testsuite>\n        <testsuite name=\"Feature\">\n            <directory suffix=\"Test.php\">./tests/Feature</directory>\n        </testsuite>\n    </testsuites>\n    <coverage processUncoveredFiles=\"true\">\n        <include>\n            <directory suffix=\".php\">./src</directory>\n        </include>\n    </coverage>\n    <php>\n        <ini name=\"display_errors\" value=\"On\" />\n        <ini name=\"display_startup_errors\" value=\"On\" />\n        <ini name=\"date.timezone\" value=\"UTC\" />\n        <ini name=\"intl.default_locale\" value=\"C.UTF-8\" />\n        <ini name=\"memory_limit\" value=\"2048M\" />\n        <env name=\"DB_CONNECTION\" value=\"sqlite\" />\n        <env name=\"DB_DATABASE\" value=\":memory:\" />\n        <env name=\"APP_KEY\" value=\"base64:2fl+Ktvkfl+Fuz4Qp/A75G2RTiWVA/ZoKZvp6fiiM10=\"/>\n    </php>\n</phpunit>"
  },
  {
    "path": "src/EagerLoadPivotBuilder.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations;\n\nuse Closure;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\n\nclass EagerLoadPivotBuilder extends Builder\n{\n    protected static $knownPivotAccessors = [\n        'pivot',\n    ];\n\n    /**\n     * Override.\n     * Eagerly load the relationship on a set of models.\n     *\n     * @param  array  $models\n     * @param  string  $name\n     * @param  \\Closure  $constraints\n     * @return array\n     */\n    protected function eagerLoadRelation(array $models, $name, Closure $constraints)\n    {\n        $this->watchForPivotAccessors($name);\n\n        if ($this->isPivotAccessor($name)) {\n            $this->eagerLoadPivotRelations($models, $name);\n            return $models;\n        }\n\n        return parent::eagerLoadRelation($models, $name, $constraints);\n    }\n\n    /**\n     * Watch for pivot accessors to register it as known pivot accessors.\n     *\n     * @param  string $name\n     * @return void\n     */\n    protected function watchForPivotAccessors($name)\n    {\n        $model = $this->getModel();\n\n        if (!method_exists($model->newInstance(), $name)) {\n            return;\n        }\n\n        $relation = $model->newInstance()->$name();\n\n        if ($relation instanceof BelongsToMany) {\n            static::$knownPivotAccessors[] = $relation->getPivotAccessor();\n        }\n    }\n\n    /**\n     * If relation name is a pivot accessor.\n     *\n     * @param  string  $name\n     * @return boolean\n     */\n    protected function isPivotAccessor($name)\n    {\n        return in_array($name, static::$knownPivotAccessors);\n    }\n\n    /**\n     * Eager load pivot relations.\n     *\n     * @param  array $models\n     * @param  string $pivotAccessor\n     * @return void\n     */\n    protected function eagerLoadPivotRelations($models, $pivotAccessor)\n    {\n        $pivots = Arr::pluck($models, $pivotAccessor);\n        $pivots = head($pivots)->newCollection($pivots);\n        $pivots->load($this->getPivotEagerLoadRelations($pivotAccessor));\n    }\n\n    /**\n     * Get the pivot relations to be eager loaded.\n     *\n     * @param string $pivotAccessor\n     * @return array\n     */\n    protected function getPivotEagerLoadRelations($pivotAccessor)\n    {\n        $relations = array_filter($this->eagerLoad, function ($relation) use ($pivotAccessor) {\n            return $relation !== $pivotAccessor && Str::contains($relation, $pivotAccessor);\n        }, ARRAY_FILTER_USE_KEY);\n\n        return array_combine(\n            array_map(function ($relation) use ($pivotAccessor) {\n                return substr($relation, strlen(\"{$pivotAccessor}.\"));\n            }, array_keys($relations)),\n            array_values($relations)\n        );\n    }\n}\n"
  },
  {
    "path": "src/EagerLoadPivotTrait.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations;\n\ntrait EagerLoadPivotTrait\n{\n    /**\n     * Create a new Eloquent query builder for the model.\n     *\n     * @param  \\Illuminate\\Database\\Query\\Builder  $query\n     * @return \\Illuminate\\Database\\Eloquent\\Builder|static\n     */\n    public function newEloquentBuilder($query)\n    {\n        return new EagerLoadPivotBuilder($query);\n    }\n}\n"
  },
  {
    "path": "tests/Database/Factories/BrandFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Brand;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\nclass BrandFactory extends Factory\n{\n    protected $model = Brand::class;\n\n    public function definition()\n    {\n        return [\n            'name' => $this->faker->word,\n            'logo' => $this->faker->imageUrl,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Database/Factories/CarFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Brand;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car>\n */\nclass CarFactory extends Factory\n{\n    protected $model = Car::class;\n\n    public function definition()\n    {\n        return [\n            'model' => $this->faker->words(rand(2, 4), true),\n            'brand_id' => function()\n            {\n                return Brand::factory()->create()->id;\n            }\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Database/Factories/CarUserFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Color;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Tire;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser>\n */\nclass CarUserFactory extends Factory\n{\n    protected $model = CarUser::class;\n\n    public function definition()\n    {\n        return [\n            'car_id'   => function() {\n                return Car::factory()->create()->id;\n            },\n            'color_id' => function() {\n                return Color::factory()->create()->id;\n            },\n            'user_id'  => function() {\n                return User::factory()->create()->id;\n            }\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Database/Factories/ColorFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Color;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Color>\n */\nclass ColorFactory extends Factory\n{\n    protected $model = Color::class;\n\n    public function definition()\n    {\n        return [\n            'name' => $this->faker->word,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Database/Factories/TireFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Tire;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Tire>\n */\nclass TireFactory extends Factory\n{\n    protected $model = Tire::class;\n\n    public function definition()\n    {\n        return [\n            'brand' => $this->faker->word,\n            'profile_depth' => $this->faker->randomNumber(2),\n            'car_user_id' => function()\n            {\n                return CarUser::factory()->create()->id;\n            }\n        ];\n    }\n}"
  },
  {
    "path": "tests/Database/Factories/UserFactory.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User;\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\nuse Illuminate\\Support\\Str;\n\n/**\n * @extends \\Illuminate\\Database\\Eloquent\\Factories\\Factory<\\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User>\n */\nclass UserFactory extends Factory\n{\n    protected $model = User::class;\n\n    public function definition()\n    {\n        return [\n            'name' => $this->faker->name,\n            'email' => $this->faker->unique()->safeEmail,\n            'email_verified_at' => now(),\n            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password\n            'remember_token' => Str::random(10),\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2014_10_12_000000_create_users_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateUsersTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('users', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n            $table->string('name');\n            $table->string('email')->unique();\n            $table->timestamp('email_verified_at')->nullable();\n            $table->string('password');\n            $table->rememberToken();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('users');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2014_10_12_100000_create_password_resets_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreatePasswordResetsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('password_resets', function (Blueprint $table) {\n            $table->string('email')->index();\n            $table->string('token');\n            $table->timestamp('created_at')->nullable();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('password_resets');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2019_06_02_131048_create_brands_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateBrandsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('brands', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n            $table->string('name');\n            $table->string('logo');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('brands');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2019_06_02_131049_create_cars_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateCarsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('cars', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n            $table->string('model');\n\n            $table->bigInteger('brand_id');\n            $table->foreign('brand_id')->references('id')->on('brands')->cascadeOnDelete();\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('cars');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2019_06_02_131100_create_colors_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateColorsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('colors', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n            $table->string('name');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('colors');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2019_06_02_131120_create_car_user_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateCarUserTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('car_user', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n\n            $table->unsignedBigInteger('car_id');\n            $table->foreign('car_id')->references('id')->on('cars')->cascadeOnDelete();\n\n            $table->unsignedBigInteger('color_id');\n            $table->foreign('color_id')->references('id')->on('colors')->cascadeOnDelete();\n\n            $table->unsignedBigInteger('user_id');\n            $table->foreign('user_id')->references('id')->on('users')->cascadeOnDelete();\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('car_user');\n    }\n}\n"
  },
  {
    "path": "tests/Database/Migrations/2019_06_02_131148_create_tires_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateTiresTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('tires', static function (Blueprint $table) {\n            $table->bigIncrements('id');\n            $table->string('brand');\n            $table->integer('profile_depth');\n\n            $table->bigInteger('car_user_id');\n            $table->foreign('car_user_id')->references('id')->on('car_user')->cascadeOnDelete();\n\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('tires');\n    }\n}"
  },
  {
    "path": "tests/Models/Brand.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\BrandFactory;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Brand extends Model\n{\n    use HasFactory;\n\n    protected $table = 'brands';\n    protected $fillable = [\n        'name',\n        'logo'\n    ];\n\n    public function cars()\n    {\n        return $this->hasMany(Car::class);\n    }\n\n    protected static function newFactory()\n    {\n        return BrandFactory::new();\n    }\n}"
  },
  {
    "path": "tests/Models/Car.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\EagerLoadPivotTrait;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\CarFactory;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n\n/**\n * @property int $id\n * @property string $model\n * @property string $make\n * @property \\Illuminate\\Support\\Carbon|null $created_at\n * @property \\Illuminate\\Support\\Carbon|null $updated_at\n * @property-read \\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User[]|null $users\n * @method static \\AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\CarFactory factory(...$parameters)\n * @method static Builder|Car newModelQuery()\n * @method static Builder|Car newQuery()\n * @method static Builder|Car query()\n * @mixin \\Eloquent\n\n */\nclass Car extends Model\n{\n    use EagerLoadPivotTrait;\n    use HasFactory;\n\n    protected $table = 'cars';\n    protected $fillable = [\n        'model',\n        'brand_id',\n    ];\n\n    public function brand()\n    {\n        return $this->belongsTo(Brand::class);\n    }\n\n    public function users()\n    {\n        return $this->belongsToMany(User::class)\n            ->withPivot('color_id')\n            ->using(CarUser::class)\n            ->as('car_user');\n    }\n\n    protected static function newFactory()\n    {\n        return CarFactory::new();\n    }\n}\n"
  },
  {
    "path": "tests/Models/CarUser.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\CarUserFactory;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Relations\\Pivot;\n\n/**\n * @property int $id\n * @property int $car_id\n * @property int $color_id\n * @property int $user_id\n * @property-read \\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car|null $car\n * @property-read \\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Color|null $color\n * @property-read \\AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User|null $user\n * @method static \\AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\CarUserFactory factory(...$parameters)\n * @method static Builder|CarUser newModelQuery()\n * @method static Builder|CarUser newQuery()\n * @method static Builder|CarUser query()\n * @mixin \\Eloquent\n */\nclass CarUser extends Pivot\n{\n    use HasFactory;\n\n    public $incrementing = true;\n    protected $table = 'car_user';\n    protected $fillable =  [\n        'car_id',\n        'color_id',\n        'user_id'\n    ];\n\n    public function car()\n    {\n        return $this->belongsTo(Car::class);\n    }\n\n    public function color()\n    {\n        return $this->belongsTo(Color::class);\n    }\n\n    public function tires()\n    {\n        return $this->hasMany(Tire::class);\n    }\n\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n\n    protected static function newFactory()\n    {\n        return CarUserFactory::new();\n    }\n}\n"
  },
  {
    "path": "tests/Models/Color.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\ColorFactory;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property int $id\n * @property string $name\n * @property \\Illuminate\\Support\\Carbon|null $created_at\n * @property \\Illuminate\\Support\\Carbon|null $updated_at\n * @method static \\AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\ColorFactory factory(...$parameters)\n * @method static Builder|Color newModelQuery()\n * @method static Builder|Color newQuery()\n * @method static Builder|Color query()\n * @mixin \\Eloquent\n */\nclass Color extends Model\n{\n    use HasFactory;\n\n    protected $table = 'colors';\n    protected $fillable = [\n        'name'\n    ];\n\n    public function cars()\n    {\n        return $this->belongsToMany(Car::class);\n    }\n\n    public function users()\n    {\n        return $this->belongsToMany(User::class);\n    }\n\n    protected static function newFactory()\n    {\n        return ColorFactory::new();\n    }\n}\n"
  },
  {
    "path": "tests/Models/Tire.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\TireFactory;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @property int $id\n * @property string $brand\n * @property int $profile_depth\n * @property int $car_user_id\n * @property \\Illuminate\\Support\\Carbon|null $created_at\n * @property \\Illuminate\\Support\\Carbon|null $updated_at\n * @method static \\AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\TireFactory factory(...$parameters)\n * @method static Builder|Tire newModelQuery()\n * @method static Builder|Tire newQuery()\n * @method static Builder|Tire query()\n * @mixin \\Eloquent\n */\nclass Tire extends Model\n{\n    use HasFactory;\n\n    protected $table = 'tires';\n    protected $fillable = [\n        'brand',\n        'profile_depth',\n        'car_user_id',\n    ];\n\n    protected static function newFactory()\n    {\n        return TireFactory::new();\n    }\n}\n"
  },
  {
    "path": "tests/Models/User.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Models;\n\nuse AjCastro\\EagerLoadPivotRelations\\EagerLoadPivotTrait;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\UserFactory;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Database\\Eloquent\\Factories\\HasFactory;\nuse Illuminate\\Foundation\\Auth\\User as Authenticatable;\n\n/**\n * @property int $id\n * @property string $name\n * @property string $email\n * @property string $password\n * @property \\Illuminate\\Support\\Carbon|null $created_at\n * @property \\Illuminate\\Support\\Carbon|null $updated_at\n * @method static \\AjCastro\\EagerLoadPivotRelations\\Tests\\Database\\Factories\\UserFactory factory(...$parameters)\n * @method static Builder|User newModelQuery()\n * @method static Builder|User newQuery()\n * @method static Builder|User query()\n * @mixin \\Illuminate\\Database\\Eloquent\n */\nclass User extends Authenticatable\n{\n    use HasFactory;\n    use EagerLoadPivotTrait;\n\n    protected $table = 'users';\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array\n     */\n    protected $fillable = [\n        'name', 'email', 'password',\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array\n     */\n    protected $hidden = [\n        'password', 'remember_token',\n    ];\n\n    /**\n     * The attributes that should be cast to native types.\n     *\n     * @var array\n     */\n    protected $casts = [\n        'email_verified_at' => 'datetime',\n    ];\n\n    public function cars()\n    {\n        return $this->belongsToMany(Car::class)\n            ->withPivot('color_id')\n            ->using(CarUser::class);\n    }\n\n    protected static function newFactory()\n    {\n        return UserFactory::new();\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests;\nuse Orchestra\\Testbench\\TestCase as BaseTestCase;\n\nclass TestCase extends BaseTestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n    }\n\n    protected function getPackageProviders($app)\n    {\n    }\n\n    protected function getEnvironmentSetUp($app)\n    {\n        ( new \\CreateUsersTable )->up();\n        ( new \\CreatePasswordResetsTable )->up();\n        ( new \\CreateBrandsTable )->up();\n        ( new \\CreateCarsTable )->up();\n        ( new \\CreateColorsTable )->up();\n        ( new \\CreateCarUserTable )->up();\n        ( new \\CreateTiresTable )->up();\n    }\n}"
  },
  {
    "path": "tests/Unit/CountTest.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Unit;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Tire;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\TestCase;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\n\nclass CountTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_it_can_use_with_count_pivot_relations()\n    {\n        $this->markTestSkipped('This could be a new feature, see #6');\n\n        $user = User::factory()->create();\n        $pivots = CarUser::factory( [ 'user_id' => $user->id ] )->count( 2 )->create();\n        $tires = rand(4, 8);\n\n        foreach($pivots as $pivot) {\n            Tire::factory(['car_user_id' => $pivot->id])\n                ->count($tires)\n                ->create();\n        }\n\n        $user = User::with( [\n            'cars',\n            'cars.pivot.color',\n            'cars.pivot' => function($query) {\n                return $query->withCount('tires');\n            }\n        ] )\n            ->find( $user->id );\n\n        $this->assertSame($tires, $user->cars[0]->pivot->tires_count);\n    }\n\n    public function test_it_can_use_load_count_pivot_relations()\n    {\n        $this->markTestSkipped('This could be a new feature, see #6');\n\n        $user = User::factory()->create();\n        $pivots = CarUser::factory( [ 'user_id' => $user->id ] )->count( 2 )->create();\n        $tires = rand(4, 8);\n\n        foreach($pivots as $pivot) {\n            Tire::factory(['car_user_id' => $pivot->id])\n                ->count($tires)\n                ->create();\n        }\n\n        $user = User::find($user->id);\n        $user->load([\n            'cars',\n            'cars.pivot.color',\n            'cars.pivot' => function($query) {\n                return $query->withCount('tires');\n            }]);\n\n        $this->assertSame($tires, $user->cars[0]->pivot->tires_count);\n    }\n}"
  },
  {
    "path": "tests/Unit/PaginateTest.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Unit;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\TestCase;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass PaginateTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_it_can_paginate_with_pivot_relations()\n    {\n        $pivots = CarUser::factory()->count( 30 )->create();\n\n        $users = User::with([\n            'cars',\n            'cars.pivot.color'\n        ])\n            ->paginate(10);\n\n        $this->assertInstanceOf(LengthAwarePaginator::class, $users);\n    }\n\n    public function test_it_can_paginate_after_eager_loading_pivot_relations()\n    {\n        $this->markTestSkipped('Failing see #3');\n        $pivots = CarUser::factory()->count( 30 )->create();\n\n        $user = User::find(1)->cars()->with(['pivot.color'])->paginate(10);\n\n        $this->assertInstanceOf(LengthAwarePaginator::class, $user);\n    }\n\n    public function test_it_can_paginate_with_custom_pivot_relations()\n    {\n        $pivots = CarUser::factory()->count( 30 )->create();\n\n        $cars = Car::with([\n            'users',\n            'users.car_user.color'\n        ])\n            ->paginate(10);\n\n        $this->assertInstanceOf(LengthAwarePaginator::class, $cars);\n    }\n\n    public function test_it_can_paginate_after_eager_loading_custom_pivot_relations()\n    {\n        $this->markTestSkipped('Failing see #3');\n        $pivots = CarUser::factory()->count( 30 )->create();\n\n        $car = Car::find(1)->users()->with(['car_user.color'])->paginate(10);\n\n        $this->assertInstanceOf(LengthAwarePaginator::class, $car);\n    }\n}"
  },
  {
    "path": "tests/Unit/PivotTest.php",
    "content": "<?php\n\nnamespace AjCastro\\EagerLoadPivotRelations\\Tests\\Unit;\n\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Car;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\CarUser;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\Color;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\Models\\User;\nuse AjCastro\\EagerLoadPivotRelations\\Tests\\TestCase;\nuse Illuminate\\Foundation\\Testing\\RefreshDatabase;\n\nclass PivotTest extends TestCase\n{\n    use RefreshDatabase;\n\n    public function test_it_can_use_with_pivot_relations()\n    {\n        $user = User::factory()->create();\n        $pivots = CarUser::factory(['user_id' => $user->id])->count( 2 )->create();\n\n        $user = User::with([\n            'cars',\n            'cars.pivot.color'\n        ])\n            ->find($user->id);\n\n        $this->assertInstanceOf(Car::class, $user->cars[0]);\n        $this->assertInstanceOf(Color::class, $user->cars[0]->pivot->color);\n    }\n\n    public function test_it_can_use_load_pivot_relations()\n    {\n        $user = User::factory()->create();\n        $pivots = CarUser::factory(['user_id' => $user->id])->count( 2 )->create();\n\n        $user->load([\n            'cars',\n            'cars.pivot.color'\n        ]);\n\n        $this->assertInstanceOf(Car::class, $user->cars[0]);\n        $this->assertInstanceOf(Color::class, $user->cars[0]->pivot->color);\n    }\n\n    public function test_it_can_use_load_missing_pivot_relations()\n    {\n        $user = User::factory()->create();\n        $pivots = CarUser::factory(['user_id' => $user->id])->count( 2 )->create();\n\n        $user->loadMissing([\n            'cars',\n            'cars.pivot.color'\n        ]);\n\n        $this->assertInstanceOf(Car::class, $user->cars[0]);\n        $this->assertInstanceOf(Color::class, $user->cars[0]->pivot->color);\n    }\n\n    public function test_it_can_use_with_custom_pivot_relations()\n    {\n        $car = Car::factory()->create();\n        $pivots = CarUser::factory(['car_id' => $car->id])->count( 2 )->create();\n\n        $car = Car::with([\n            'users',\n            'users.car_user.color'\n        ])\n            ->find($car->id);\n\n        $this->assertInstanceOf(User::class, $car->users[0]);\n        $this->assertInstanceOf(Color::class, $car->users[0]->car_user->color);\n    }\n\n    public function test_it_can_use_load_custom_pivot_relations()\n    {\n        $car = Car::factory()->create();\n        $pivots = CarUser::factory(['car_id' => $car->id])->count( 2 )->create();\n\n        $car->load([\n            'users',\n            'users.car_user.color'\n        ]);\n\n        $this->assertInstanceOf(User::class, $car->users[0]);\n        $this->assertInstanceOf(Color::class, $car->users[0]->car_user->color);\n    }\n\n    public function test_it_can_use_load_missing_custom_pivot_relations()\n    {\n        $car = Car::factory()->create();\n        $pivots = CarUser::factory(['car_id' => $car->id])->count( 2 )->create();\n\n        $car->loadMissing([\n            'users',\n            'users.car_user.color'\n        ]);\n\n        $this->assertInstanceOf(User::class, $car->users[0]);\n        $this->assertInstanceOf(Color::class, $car->users[0]->car_user->color);\n    }\n}"
  }
]