{"id":22944338,"url":"https://github.com/clickbar/laravel-custom-relations","last_synced_at":"2025-08-12T22:31:58.348Z","repository":{"id":229172311,"uuid":"765632633","full_name":"clickbar/laravel-custom-relations","owner":"clickbar","description":"Relate everything with maximum flexibility 💍🖖🏻","archived":false,"fork":false,"pushed_at":"2024-07-08T01:35:32.000Z","size":87,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-12-06T14:23:30.974Z","etag":null,"topics":["eloquent","laravel","laravel-package","php","relationships"],"latest_commit_sha":null,"homepage":"","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/clickbar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"clickbar"}},"created_at":"2024-03-01T10:04:43.000Z","updated_at":"2024-07-08T01:35:35.000Z","dependencies_parsed_at":"2024-07-08T02:46:30.333Z","dependency_job_id":"5f17d6cf-5cab-463f-bcc5-6e7e169a3874","html_url":"https://github.com/clickbar/laravel-custom-relations","commit_stats":null,"previous_names":["clickbar/laravel-custom-relations"],"tags_count":2,"template":false,"template_full_name":"spatie/package-skeleton-laravel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clickbar%2Flaravel-custom-relations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clickbar%2Flaravel-custom-relations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clickbar%2Flaravel-custom-relations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clickbar%2Flaravel-custom-relations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clickbar","download_url":"https://codeload.github.com/clickbar/laravel-custom-relations/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229711216,"owners_count":18112099,"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":["eloquent","laravel","laravel-package","php","relationships"],"created_at":"2024-12-14T14:17:43.847Z","updated_at":"2024-12-14T14:17:44.391Z","avatar_url":"https://github.com/clickbar.png","language":"PHP","funding_links":["https://github.com/sponsors/clickbar"],"categories":[],"sub_categories":[],"readme":"# Laravel Custom Relations\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/clickbar/laravel-custom-relations.svg?style=flat-square)](https://packagist.org/packages/clickbar/laravel-custom-relations)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/clickbar/laravel-custom-relations/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/clickbar/laravel-custom-relations/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/clickbar/laravel-custom-relations/fix-php-code-style-issues.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/clickbar/laravel-custom-relations/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/clickbar/laravel-custom-relations.svg?style=flat-square)](https://packagist.org/packages/clickbar/laravel-custom-relations)\n\nLaravel provides some pretty good relations from scratch. If those relations do not fit the need, the community has provided a lot of other relation packages.\nEspecially [staudenmeir](https://github.com/staudenmeir) did a lot if nice work on that end. However, in our projects we encountered the need of some really custom relations that could easily be expressed with an eloquent query, but not with default relations.\nTherefore, we created this package to give you the full control over your relations.\n\n## Introduction\nSometimes it needs to be more custom.\nThis package extends the default Laravel Relations with Relations that can be described by a query. \n\nFor explanation purposes we consider the following model with a simple concatenated relation use case.\n(for cases like this you should also have a look  [eloquent-has-many-deep](https://github.com/staudenmeir/eloquent-has-many-deep) from staudenmeir).\nEven the example is quite simple, it should be able to represent the huge amount of possibilities that comes with custom relations.\n![model chain](art/models.png)\n\nLet's explorer the connection between Client and Task in the default Laravel way:\n```php\n$client = $task-\u003eorder-\u003eproject-\u003eclient;\n$tasks = $client-\u003eprojects-\u003eflatMap(fn(Project $project) =\u003e $project-\u003eorder-\u003eflatMap(fn(Order $order) =\u003e $order-\u003etasks));\n```\n\nWouldn't it be cool to do stuff like this with only 1 single database query?\n```php\n$client = $task-\u003eclient;\n$tasks = $client-\u003etasks;\n```\n\nWith Custom Relations you can do this with only one single Database Query.\n\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require clickbar/laravel-custom-relations\n```\n\n## Preparing the Model\nIn order to use the Custom Relations, you must use the ``HasCustomRelation`` trait:\n\n```php\nuse Clickbar\\LaravelCustomRelations\\Traits\\HasCustomRelation;\n\n\nclass Client extends Model{\n    \n    use HasCustomRelation;\n    \n    ...\n}\n```\n\n## Writing the Relation\nLike you know from Laravel, relations can return a collection of models or just one model.\nTherefore, this package has two Different Relations ``CustomRelation`` and ``CustomRelationSingle``.\n\nLet's look at our two examples from above: \n```php\nclass Task extends Model {\n\n    use HasCustomRelation;\n\n    public function client(): CustomRelationSingle {\n        return $this-\u003ecustomRelationSingle(\n            Client::class,\n            function ($query) {\n                $query\n                    -\u003ejoin('projects', 'clients.id', 'client_id')\n                    -\u003ejoin('orders', 'projects.id', 'project_id')\n                    -\u003ejoin('tasks', 'orders.id', 'order_id');\n            },\n        );\n    }\n}\n```\n\n```php\nclass Client extends Model {\n\n    use HasCustomRelation;\n\n    public function tasks(): CustomRelation {\n        return $this-\u003ecustomRelation(\n            Task::class,\n            function ($query) {\n                $query\n                    -\u003ejoin('orders', 'orders.id', 'order_id')\n                    -\u003ejoin('projects', 'projects.id', 'project_id')\n                    -\u003ejoin('clients', 'clients.id', 'client_id');\n            },\n        );\n    }\n}\n```\n\nLike regular Laravel Relations, the query builder starts from the related model.\nThis results in the following join chains:  \n$task-\u003eclient: ``Client-\u003eProjects-\u003eOrders-\u003eTasks``  \n$client-\u003etasks: ``Tasks-\u003eOrders-\u003eProjects-\u003eClient``\n\nIf you prefer starting the join from the model the relation is defined on, you can use the method with the ``fromParent`` suffix:\n```php\nclass Task extends Model {\n\n    use HasCustomRelation;\n\n    public function client(): CustomRelationSingle {\n        return $this-\u003ecustomRelationFromParentSingle(\n            Client::class,\n            function ($query) {\n                $query\n                    -\u003ejoin('orders', 'orders.id', 'order_id')\n                    -\u003ejoin('projects', 'projects.id', 'project_id')\n                    -\u003ejoin('clients', 'clients.id', 'client_id');\n            },\n        );\n    }\n}\n```\n\n```php\nclass Client extends Model {\n\n    use HasCustomRelation;\n\n    public function tasks(): CustomRelation {\n        return $this-\u003ecustomRelationFromParent(\n            Task::class,\n            function ($query) {\n                $query\n                    -\u003ejoin('projects', 'clients.id', 'client_id')\n                    -\u003ejoin('orders', 'projects.id', 'project_id')\n                    -\u003ejoin('tasks', 'orders.id', 'order_id');\n            },\n        );\n    }\n}\n```\n\n## Limitations\nSince the query might introduce a lot of joins, some methods known from Laravel Relations are not available:\n- make\n- create\n- update\n- forceCreate\n- forceDelete\n\n## Testing\n\n```bash\ncomposer test\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Security Vulnerabilities\n\nPlease review [our security policy](../../security/policy) on how to report security vulnerabilities.\n\n## Credits\n\n- [Adrian Hawlitschek](https://github.com/53199186+ahawlitschek)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclickbar%2Flaravel-custom-relations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclickbar%2Flaravel-custom-relations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclickbar%2Flaravel-custom-relations/lists"}