{"id":23505648,"url":"https://github.com/tylernathanreed/laravel-composite-relations","last_synced_at":"2025-09-18T22:52:07.693Z","repository":{"id":55430010,"uuid":"287611003","full_name":"tylernathanreed/laravel-composite-relations","owner":"tylernathanreed","description":"Adds the ability to have multiple foreign keys in a relation.","archived":false,"fork":false,"pushed_at":"2025-06-19T23:17:39.000Z","size":135,"stargazers_count":16,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-18T06:33:53.716Z","etag":null,"topics":["eloquent","laravel","php"],"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/tylernathanreed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2020-08-14T19:39:13.000Z","updated_at":"2025-06-19T23:09:51.000Z","dependencies_parsed_at":"2023-12-22T22:26:17.932Z","dependency_job_id":"76a4de65-1588-4cd1-9200-8e79349818c8","html_url":"https://github.com/tylernathanreed/laravel-composite-relations","commit_stats":{"total_commits":28,"total_committers":1,"mean_commits":28.0,"dds":0.0,"last_synced_commit":"3e9b667b88358280bda87affc13553487240f505"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/tylernathanreed/laravel-composite-relations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylernathanreed%2Flaravel-composite-relations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylernathanreed%2Flaravel-composite-relations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylernathanreed%2Flaravel-composite-relations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylernathanreed%2Flaravel-composite-relations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tylernathanreed","download_url":"https://codeload.github.com/tylernathanreed/laravel-composite-relations/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylernathanreed%2Flaravel-composite-relations/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275847221,"owners_count":25539345,"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","status":"online","status_checked_at":"2025-09-18T02:00:09.552Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","php"],"created_at":"2024-12-25T09:37:28.827Z","updated_at":"2025-09-18T22:52:06.595Z","avatar_url":"https://github.com/tylernathanreed.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laravel Composite Relations\n\n[![Laravel Version](https://img.shields.io/badge/Laravel-10.x%2F11.x-blue)](https://laravel.com/)\n[![Tests](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/tests.yml/badge.svg)](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/tests.yml)\n[![Lint](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/coding-standards.yml/badge.svg)](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/coding-standards.yml)\n[![Static Analysis](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/tylernathanreed/laravel-composite-relations/actions/workflows/static-analysis.yml)\n[![Total Downloads](https://poser.pugx.org/reedware/laravel-composite-relations/downloads)](//packagist.org/packages/reedware/laravel-composite-relations)\n\nThis package adds the ability to have multiple foreign keys in a relation.\n\n## Introduction\n\nEloquent does not natively support using composite keys in relationships. While single key relationships are typically preferred, there are times where they are unfortunately needed, and there's good way around it. This package offers a solution where you can use composite keys, and everything still feels like it's Eloquent.\n\nThis package will allow you to define the following composite relations:\n* Belongs To\n* Has One\n* Has Many\n\nAll composite relations support eager loading and existence queries (e.g. \"where has\").\n\nThere currently is no intention to add support for additional relations, as these should be enough for the vast majority of use cases.\n\n## Installation\n\n#### Using Composer\n\n```\ncomposer require reedware/laravel-composite-relations\n```\n\n#### Versioning\n\nThis package is maintained with the latest version of Laravel in mind, but support follows Laravel's [Support Policy](https://laravel.com/docs/master/releases#support-policy).\n\n| Package | Laravel     | PHP        |\n| :-----: | :---------: | :--------: |\n|     4.x | 10.x - 11.x | 8.1 - 8.3+ |\n|     3.x |  8.x - 10.x | 7.2 - 8.0+ |\n|     2.x |  6.x -  8.x | 7.2 - 8.0+ |\n|     1.x |  5.5 -  5.8 | 7.1 - 7.3+ |\n\n#### Code Changes\n\nThis package does not use a service provider or facade, but rather a trait. On your base model instance, you'll want to include the following:\n\n```php\nuse Illuminate\\Database\\Eloquent\\Model as Eloquent;\nuse Reedware\\LaravelCompositeRelations\\HasCompositeRelations;\n\nabstract class Model extends Eloquent\n{\n    use HasCompositeRelations;\n}\n```\n\n## Usage\n\n### 1. Defining Relations\n\n#### Composite Belongs To\n\nImagine you were defining a *non-composite* belongs to relation:\n\n```php\npublic function myRelation()\n{\n    return $this-\u003ebelongsTo(MyRelated::class, 'my_column_on_this_table', 'my_column_on_the_other_table');\n}\n```\n\nSince composite relations use multiple keys, you'll simply define the keys as an array:\n\n```php\npublic function myCompositeRelation()\n{\n    return $this-\u003ecompositeBelongsTo(MyRelated::class, ['my_first_key', 'my_second_key'], ['their_first_key', 'their_second_key']);\n}\n```\n\n#### Composite Has One\n\nThis follows the same structure as the composite belongs to relation:\n\n```php\npublic function myCompositeRelation()\n{\n    return $this-\u003ecompositeHasOne(MyRelated::class, ['their_first_key', 'their_second_key'], ['my_first_key', 'my_second_key']);\n}\n```\n\n#### Composite Has Many\n\nThe pattern continues:\n\n```php\npublic function myCompositeRelation()\n{\n    return $this-\u003ecompositeHasMany(MyRelated::class, ['foreign_1', 'foreign_2'], ['local_1', 'local_2']);\n}\n```\n\n### 2. Omitting Foreign and Local Keys\n\nWith non-composite relationships, you aren't actually required to provide the foreign and local key, assuming you follow a certain convention. This functionality is also available for composite relations, but must be defined differently. Here's how:\n\n```php\nclass Task extends Models\n{\n    /**\n     * The primary keys for the model.\n     *\n     * @var array\n     */\n    protected $primaryKeys = ['vendor_id', 'vendor_name'];\n\n    public function importSummary()\n    {\n        return $this-\u003ecompositeHasOne(TaskImportSummary::class);\n    }\n}\n\nclass TaskImportSummary extends Models\n{\n    public function task()\n    {\n        return $this-\u003ecompositeBelongsTo(TaskImportSummary::class);\n    }\n}\n```\n\n### 3. Joining through Composite Relations\n\nThis package is compatible with [reedware/laravel-relation-joins](https://github.com/tylernathanreed/laravel-relation-joins), meaning you can join through composite relations just like anything else:\n\n```php\n$task-\u003ejoinRelation('importSummary', function($join) {\n    $join-\u003ewhere('task_import_summaries.name', 'like', '%Relation joins are cool!%');\n});\n```\n\nYou must separately include [reedware/laravel-relation-joins](https://github.com/tylernathanreed/laravel-relation-joins) for this to work.\n\n### 4. Using composite `and` glue\n\n\nThe default glue between composite keys is `'or'`. Meaning your query will be like:\n```sql\nwhere ((\"foreign_1\" = ? or \"foreign_2\" = ?) or (\"foreign_1\" = ? or \"foreign_2\" = ?))\n```\n\nYou can change that by passing `'and'` for the glue parameter:\n```php\npublic function myCompositeBelongsToRelation()\n{\n    return $this-\u003ecompositeBelongsTo(MyRelated::class, ['local_1', 'local_2'], ['foreign_1', 'foreign_2'], null, 'and');\n}\n\npublic function myCompositeHasOneRelation()\n{\n    return $this-\u003ecompositeHasOne(MyRelated::class, ['foreign_1', 'foreign_2'], ['local_1', 'local_2'], 'and');\n}\n\npublic function myCompositeHasManyRelation()\n{\n    return $this-\u003ecompositeHasMany(MyRelated::class, ['foreign_1', 'foreign_2'], ['local_1', 'local_2'], 'and');\n}\n```\n\nGiving this result :\n```sql\nwhere ((\"foreign_1\" = ? and \"foreign_2\" = ?) or (\"foreign_1\" = ? and \"foreign_2\" = ?))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylernathanreed%2Flaravel-composite-relations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftylernathanreed%2Flaravel-composite-relations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylernathanreed%2Flaravel-composite-relations/lists"}