{"id":15857855,"url":"https://github.com/ardalanamini/laravel-custom-relation","last_synced_at":"2025-03-15T22:31:27.892Z","repository":{"id":28068837,"uuid":"116116832","full_name":"ardalanamini/laravel-custom-relation","owner":"ardalanamini","description":"Create your own custom relation for when stock relations aren't enough","archived":false,"fork":false,"pushed_at":"2023-09-16T15:27:28.000Z","size":11,"stargazers_count":4,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-27T04:24:32.912Z","etag":null,"topics":["custom","eloquent","laravel","relation","relationship"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ardalanamini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-03T09:14:46.000Z","updated_at":"2023-09-16T15:21:12.000Z","dependencies_parsed_at":"2022-07-17T05:16:02.587Z","dependency_job_id":null,"html_url":"https://github.com/ardalanamini/laravel-custom-relation","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardalanamini%2Flaravel-custom-relation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardalanamini%2Flaravel-custom-relation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardalanamini%2Flaravel-custom-relation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardalanamini%2Flaravel-custom-relation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ardalanamini","download_url":"https://codeload.github.com/ardalanamini/laravel-custom-relation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243801600,"owners_count":20350105,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["custom","eloquent","laravel","relation","relationship"],"created_at":"2024-10-05T20:42:18.725Z","updated_at":"2025-03-15T22:31:22.884Z","avatar_url":"https://github.com/ardalanamini.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Custom Relation\n\nCreate your own custom relation for when stock relations aren't enough\n\n[TOC]\n\n## Use this if...\n\n* None of the stock Relations fit the bill. (BelongsToManyThrough, etc)\n\n## Installation\n\nThe recommended way to install is with [composer](http://getcomposer.org/):\n\n```shell\ncomposer require ardalanamini/laravel-custom-relation\n```\n\n## Example\n\nLet's say we have 3 models:\n\n- `User`\n- `Role`\n- `Permission`\n\nLet's also say `User` has a many-to-many relation with `Role`, and `Role` has a many-to-many relation with `Permission`.\n\nSo their models might look something like this. (I kept them brief on purpose.)\n\n```php\nclass User {\n    public function roles() {\n        return $this-\u003ebelongsToMany(Role::class);\n    }\n}\n```\n\n```php\nclass Role {\n    public function users() {\n        return $this-\u003ebelongsToMany(User::class);\n    }\n\n    public function permissions() {\n        return $this-\u003ebelongsToMany(Permission::class);\n    }\n}\n```\n\n```php\nclass Permission {\n    public function roles() {\n        return $this-\u003ebelongsToMany(Role::class);\n    }\n}\n```\n\n**What if you wanted to get all the `Permission`s for a `User`, or all the `User`s with a particular `Permission`?** There no stock Relation in Laravel to descibe this. What we need is a `BelongsToManyThrough` but no such thing exists in stock Laravel.\n\n## Solution\n\nFirst, make sure your models are using the `HasCustomRelations` trait. Then, define custom relations like this.\n\n```php\nuse LaravelCustomRelation\\HasCustomRelations;\n\nclass User {\n    use HasCustomRelations;\n\n    /**\n     * Get the related permissions\n     *\n     * @return Illuminate\\Database\\Eloquent\\Relations\\Relation\n     */\n    public function permissions() {\n        return $this-\u003ecustom(\n            Permission::class,\n\n            // add constraints\n            function ($relation) {\n                $relation-\u003egetQuery()\n                    // join the pivot table for permission and roles\n                    -\u003ejoin('permission_role', 'permission_role.permission_id', '=', 'permissions.id')\n                    // join the pivot table for users and roles\n                    -\u003ejoin('role_user', 'role_user.role_id', '=', 'permission_role.role_id')\n                    // for this user\n                    -\u003ewhere('role_user.user_id', $this-\u003eid);\n            },\n\n            // add eager constraints\n            function ($relation, $models) {\n                $relation-\u003egetQuery()-\u003ewhereIn(\n                  'role_user.user_id',\n                  collect($models)-\u003emap(function ($value) {\n                      return $value-\u003egetKey();\n                  })-\u003evalues()-\u003eunique()-\u003esort()-\u003eall()\n               );\n            }\n        );\n    }\n}\n```\n\n```php\nuse LaravelCustomRelation\\HasCustomRelations;\n\nclass Permission {\n    use HasCustomRelations;\n\n    /**\n     * Get the related users\n     *\n     * @return Illuminate\\Database\\Eloquent\\Relations\\Relation\n     */\n    public function users() {\n        return $this-\u003ecustom(\n            User::class,\n\n            // constraints\n            function ($relation) {\n                $relation-\u003egetQuery()\n                    // join the pivot table for users and roles\n                    -\u003ejoin('role_user', 'role_user.user_id', '=', 'users.id')\n                    // join the pivot table for permission and roles\n                    -\u003ejoin('permission_role', 'permission_role.role_id', '=', 'role_user.role_id')\n                    // for this permission\n                    -\u003ewhere('permission_role.permission_id', $this-\u003eid);\n            },\n\n            // eager constraints\n            function ($relation, $models) {\n                $relation-\u003egetQuery()-\u003ewhereIn(\n                    'permission_role.permission_id',\n                    collect($models)-\u003emap(function ($value) {\n                        return $value-\u003egetKey();\n                    })-\u003evalues()-\u003eunique()-\u003esort()-\u003eall()\n                );\n            }\n        );\n    }\n}\n```\n\nYou could now do all the normal stuff for relations without having to query in-between relations first.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fardalanamini%2Flaravel-custom-relation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fardalanamini%2Flaravel-custom-relation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fardalanamini%2Flaravel-custom-relation/lists"}