{"id":24764088,"url":"https://github.com/stillat/relationships","last_synced_at":"2025-10-28T22:38:36.559Z","repository":{"id":40313732,"uuid":"492583476","full_name":"Stillat/relationships","owner":"Stillat","description":"Provides automated bi-directional @statamic entry relationships","archived":false,"fork":false,"pushed_at":"2024-06-29T19:05:14.000Z","size":168,"stargazers_count":21,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-08T22:03:02.171Z","etag":null,"topics":[],"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/Stillat.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":"JohnathonKoster"}},"created_at":"2022-05-15T19:27:19.000Z","updated_at":"2025-07-18T22:18:02.000Z","dependencies_parsed_at":"2023-01-21T06:01:40.049Z","dependency_job_id":"429a7e5e-f662-4759-9f62-8cab0f316261","html_url":"https://github.com/Stillat/relationships","commit_stats":{"total_commits":23,"total_committers":2,"mean_commits":11.5,"dds":"0.17391304347826086","last_synced_commit":"36b2e6abe19a9daadc651d0e57a62e5457c91f74"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/Stillat/relationships","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Frelationships","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Frelationships/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Frelationships/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Frelationships/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Stillat","download_url":"https://codeload.github.com/Stillat/relationships/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Stillat%2Frelationships/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279007341,"owners_count":26084282,"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-10-11T02:00:06.511Z","response_time":55,"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":[],"created_at":"2025-01-28T21:32:37.256Z","updated_at":"2025-10-11T13:30:17.242Z","avatar_url":"https://github.com/Stillat.png","language":"PHP","funding_links":["https://github.com/sponsors/JohnathonKoster"],"categories":[],"sub_categories":[],"readme":"# Entry Relationships\n\n\u003e Entry Relationships provides a simple way to keep related Statamic entries in sync, automatically.\n\n## Overview\n\nEntry relationships can help to dramatically simplify keeping related Entries in sync with each other.\n\nFor example, if you had a `conferences` collection that had a `sponsored_by` (containing a list of sponsors) field that needed to be kept in sync with a `sponsors` collection that contained a `sponsoring` field (containing a list of conferences that sponsor is sponsoring), the Entry Relationships addon lets you express this relationship like so:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'conferences.sponsored_by',\n            'sponsors.sponsoring'\n        );\n    }\n}\n```\n\nOnce a relationship has been created, Entry Relationships will leverage Statamic's entry events to keep things in sync automatically.\n\nRelationships are also bi-directional. Updating the conference entries will automatically add the conference to any related sponsors. Updated the sponsors instead? No problem! Any conferences those sponsors are related to will also be updated!\n\nEntry Relationships will keep track of and automatically apply the following types of updates:\n\n* New entry relationship: A new sponsor was added to a conference. The conference will also be added to the `sponsors` entry.\n* A relationship being removed: A sponsor was removed from a conference. The conference will also be removed from the `sponsors` entry.\n* Related entry being deleted: A `conferences` entry was deleted. Any `sponsors` that reference the deleted `conferences` will be updated, and have that conference removed.\n\n## How to Install\n\nYou can search for this addon in the `Tools \u003e Addons` section of the Statamic control panel and click **install**, or run the following command from your project root:\n\n``` bash\ncomposer require stillat/relationships\n```\n\n## How to Use\n\nMade it past the introduction? Fantastic! Entry Relationships supports a number of relationship types, as well as provides a few helper commands.\n\n### Types of Relationships\n\nEntry Relationships supports the following types of relationships:\n\n* **Many to Many**: There may be many conferences supported by any number of sponsors, and each sponsor can support any number of conferences.\n* **Many to One**: Many books may be written by a single author.\n* **One to Many**: An author may have written many books.\n* **One to One**: A specific job position may only be filled by one employee, and a single employee can only hold a single position at a time.\n\n### Supported Data Entities\n\nEntry Relationships supports the following data entities:\n\n* **Entries**: Collection entries.\n* **Users**: Individual users.\n* **Terms**: Taxonomy terms.\n\nBy default, Entry Relationships will assume that the relationship is between entries for backwards compatibility. To\ncreate a relationship between users and your entries, you will need to prefix the relationship with the data type to\nuse when evaluating the relationship.\n\nAs an example, to create a relationship between a collection of conferences and the users who are managing those\nconferences, we could use something similar to the following:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'user:managing_conferences',\n            'conferences.managed_by'\n        );\n    }\n}\n```\n\nNote that we only have to specify the field name when referencing users.\n\nTo create a Taxonomy Terms relationship, we must specify the entity type as well as the taxonomy name:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'term:topics.posts',\n            'posts.topics'\n        );\n    }\n}\n````\n\n### Creating a Many to Many Relationship\n\n\u003e Example: Conferences can have many sponsors. Each sponsor can support many conferences.\n\nTo create a many to many relationship, you will need two collections. Each collection should contain an [entries](https://statamic.dev/fieldtypes/entries) field, referencing the other collection. Both of these fields will need to allow multiple entries to be associated.\n\nFor example, assuming the following collection setup:\n\nA `conferences` collection containing a `sponsored_by` field referencing the `sponsors` collection:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: sponsored_by\n        field:\n          mode: default\n          create: true\n          collections:\n            - sponsors\n          display: Sponsors\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Conferences\n```\n\nand a `sponsors` collection referencing the `conferences` collection:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: sponsoring\n        field:\n          mode: default\n          create: true\n          collections:\n            - conferences\n          display: Sponsoring\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Sponsors\n\n```\n\nThe following relationship can be defined within your site's service provider (`app/Providers/AppServiceProvider.php`):\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'conferences.sponsored_by',\n            'sponsors.sponsoring'\n        );\n    }\n}\n```\n\nThe `manyToMany` method will automatically define the inverse relationship for you. It is *not* necessary to define a many to many relationship from sponsors to conferences.\n\nIf you need to create multiple many-to-many relationships, you may choose to use set syntax, which providers a shortcut for defining multiple relationships. For example, to\nrelate many collections to a taxonomy, you could use the following:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'term:categories.field_name',\n            'entry:{collection1,collection2,collection3,collection4}.field_name'\n        );\n    }\n}\n```\n\nThe above example will create a many-to-many relationship between the `categories` taxonomy and the `field_name` field, and is equivalent to the following:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'term:categories.field_name',\n            'entry:collection1.field_name'\n        );\n        \n        Relate::manyToMany(\n            'term:categories.field_name',\n            'entry:collection2.field_name'\n        );\n\n        Relate::manyToMany(\n            'term:categories.field_name',\n            'entry:collection3.field_name'\n        );\n\n        Relate::manyToMany(\n            'term:categories.field_name',\n            'entry:collection4.field_name'\n        );\n    }\n}\n```\n\n### Creating a One to Many Relationship\n\n\u003e Example: Many books can be written by one author. Each author can write many books.\n\nTo create a many to one relationship, you will need two collections. Each collection should contain an [entries](https://statamic.dev/fieldtypes/entries) field, referencing the other collection.\n\nFor this relationship, the collection that can be associated to a single other entry (`books` in this example) should have their entries field set to `max_items: 1`. The collection that can have many items associated with it (`authors` in this example) should have their entries field set to allow multiple associated entries.\n\nUsing a `books` collection referencing a single author:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: content\n        field:\n          type: markdown\n          localizable: true\n      -\n        handle: author\n        field:\n          max_items: 1\n          mode: default\n          create: true\n          collections:\n            - authors\n          display: Author\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Books\n\n```\n\nand an `authors` collection referencing many books:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: content\n        field:\n          type: markdown\n          localizable: true\n      -\n        handle: books\n        field:\n          mode: default\n          create: true\n          collections:\n            - books\n          display: Books\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Authors\n\n```\n\nThe following relationship can be defined within your site's service provider (`app/Providers/AppServiceProvider.php`):\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::oneToMany(\n            'books.author',\n            'authors.books'\n        );\n    }\n}\n```\n\nThe `oneToMany` method will automatically create the inverse `manyToOne` relationship for you. You do *not* need to create a relationship from `authors.books` to `books.author`.\n\n## Creating a Many to One Relationship\n\n\u003e Example: An author can write many books. Each book is written by a single author.\n\nThis relationship is the inverse of the one to many relationship.\n\nUsing the same setup from the `Creating a One to Many Relationship` section, a many to one relationship can be defined like so:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToOne(\n            'authors.books',\n            'books.author'\n        );\n    }\n}\n```\n\nWhen using the `manyToOne` method, you do not need to define the `oneToMany` inverse relationship from `books.author` to `authors.books`. This is done automatically for you.\n\n### Creating a One to One Relationship\n\n\u003e Example: A job position may be held by a single employee. A single employee may only have one job at a time.\n\nTo create a many to one relationship, you will need two collections. Each collection should contain an [entries](https://statamic.dev/fieldtypes/entries) field, referencing the other collection. Each field must contain the `max_items: 1` configuration property.\n\nAssuming an `employees` collection:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: position\n        field:\n          max_items: 1\n          mode: default\n          create: true\n          collections:\n            - positions\n          display: Position\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Employees\n\n```\n\nand a `positions` collection:\n\n```yaml\nsections:\n  main:\n    display: Main\n    fields:\n      -\n        handle: title\n        field:\n          type: text\n          required: true\n          validate:\n            - required\n      -\n        handle: filled_by\n        field:\n          max_items: 1\n          mode: default\n          create: true\n          collections:\n            - employees\n          display: 'Filled By'\n          type: entries\n          icon: entries\n          listable: hidden\n          instructions_position: above\n          read_only: false\ntitle: Positions\n\n```\n\n\nThe following relationship can be defined within your site's service provider (`app/Providers/AppServiceProvider.php`):\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::oneToOne(\n            'employees.position',\n            'positions.filled_by'\n        );\n    }\n}\n```\n\nYou do *not* need to define the inverse relationship from `positions.filled_by` to `employees.position`. This is done automatically for you.\n\n## Other Things\n\nEach relationship has a few properties that you can use to control how Entry Relationships handles them. These are:\n\n* **withEvents**: This is `false` by default. When `true`, each updated entry will also emit their own `EntrySaving` and `EntrySaved` events\n* **allowDelete**: This is `true` by default. When `true` deleting an entry will remove that entry from any associated entries\n\nThese properties can be adjusted by calling their corresponding methods after defining the relationship:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::manyToMany(\n            'conferences.sponsored_by', \n            'sponsors.sponsoring'\n        )-\u003eallowDelete(false)-\u003ewithEvents(true);\n    }\n}\n```\n\nAdditionally, you can define your own relationships manually (but it is much easier to use one of the previously covered methods):\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse Stillat\\Relationships\\Support\\Facades\\Relate;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Relate::collection('conferences')\n                -\u003efield('sponsored_by')\n            -\u003eisRelatedTo('sponsors')\n            -   \u003ethrough('sponsoring')\n            -\u003emanyToMany();\n    }\n}\n```\n\nThe automatic inverse relationships are *not* created when defining relationships manually.\n\n## Console Commands\n\nThe Entry Relationships addon provides a few console commands that can help simplify implementation and debugging.\n\nThe addon provides the following commands:\n\n* `php please relate:list`: Lists all defined relationships and their details\n* `php please relate:fill`: Forces the addon to check all entries are in sync with each other. If not, they will be updated.\n\n### The `relate:list` Command\n\nRunning `php please relate:list` will display a table of all defined relationships:\n\n![Relationship List Table](images/relate_list.png)\n\nThe first column displays an index number for each relationship. It has no meaning other than to help relate automatically created inverse relationships.\n\n* **Primary Collection**: The collection that appears first in the relationship (the first collection handle provided, or the *left* collection)\n* **Related Collection**: The collection that appears last when defining the relationship (the second collection handle provided, or the *right* collection)\n* **Primary Field**: The field handle being used for the relationship, defined in the *primary* collection\n* **Related Field**: The field handle being used for the relationship, defined in the *related* collection\n* **Relationship**: A human friendly description of the relationship's type\n* **With Events**: Indicates if entries will saved quietly, or not\n* **Allow Deletes**: Indicates if related entries will be updated when their related entries are deleted\n* **Is Automatic Inverse**: Indicates if the relationship was automatically created for you. If so, the relationship's index you defined will appear after it in parenthesis.\n\nYou can limit the results returned to a single collection like so:\n\n```bash\nphp please relate:list collection\n```\n\n### The `relate:fill` Command\n\nThis command can be used to force the Entry Relationships addon to check and update all related entries.\n\nA common use case for this is when you already had a `books` collection and have associated their `author`. Later on, you add a `books` field to the `authors` collection. Running this command will bring the `books` and `authors` entries in sync for you.\n\nThe `relate:fill` command supports a few options:\n\n| Option | Description |\n|---|---|\n| `--dry` | Useful to see what entries would be updated, without actually updating them. |\n| `-v` | Adds the count of added, removed, and unchanged items to the output. |\n| `-vv` | Outputs the entry IDs when it performs an update. |\n| `-vvv` | Outputs everything. |\n\nYou can limit the operation to a single collection like so:\n\n```bash\nphp please relate:fill collection\n```\n\n## License\n\nEntry Relationships is free software released under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstillat%2Frelationships","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstillat%2Frelationships","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstillat%2Frelationships/lists"}