{"id":15277451,"url":"https://github.com/tattersoftware/codeigniter4-relations","last_synced_at":"2025-04-06T19:13:35.966Z","repository":{"id":41827716,"uuid":"207672042","full_name":"tattersoftware/codeigniter4-relations","owner":"tattersoftware","description":"Entity relationships for CodeIgniter 4","archived":false,"fork":false,"pushed_at":"2024-07-09T13:08:54.000Z","size":151,"stargazers_count":89,"open_issues_count":7,"forks_count":20,"subscribers_count":7,"default_branch":"develop","last_synced_at":"2025-03-30T17:11:12.350Z","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/tattersoftware.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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-10T22:09:41.000Z","updated_at":"2025-03-23T15:19:38.000Z","dependencies_parsed_at":"2024-07-09T16:24:08.965Z","dependency_job_id":null,"html_url":"https://github.com/tattersoftware/codeigniter4-relations","commit_stats":{"total_commits":55,"total_committers":4,"mean_commits":13.75,"dds":0.4545454545454546,"last_synced_commit":"7d96b9f8e825d09f3c7c7a821d142b08fbf4dd07"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tattersoftware%2Fcodeigniter4-relations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tattersoftware%2Fcodeigniter4-relations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tattersoftware%2Fcodeigniter4-relations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tattersoftware%2Fcodeigniter4-relations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tattersoftware","download_url":"https://codeload.github.com/tattersoftware/codeigniter4-relations/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247535520,"owners_count":20954576,"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":[],"created_at":"2024-09-30T11:06:30.971Z","updated_at":"2025-04-06T19:13:35.942Z","avatar_url":"https://github.com/tattersoftware.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tatter\\Relations\nEntity relationships for CodeIgniter 4\n\n[![](https://github.com/tattersoftware/codeigniter4-relations/workflows/PHPUnit/badge.svg)](https://github.com/tattersoftware/codeigniter4-relations/actions/workflows/phpunit.yml)\n[![](https://github.com/tattersoftware/codeigniter4-relations/workflows/PHPStan/badge.svg)](https://github.com/tattersoftware/codeigniter4-relations/actions/workflows/phpstan.yml)\n[![](https://github.com/tattersoftware/codeigniter4-relations/workflows/Deptrac/badge.svg)](https://github.com/tattersoftware/codeigniter4-relations/actions/workflows/deptrac.yml)\n[![Coverage Status](https://coveralls.io/repos/github/tattersoftware/codeigniter4-relations/badge.svg?branch=develop)](https://coveralls.io/github/tattersoftware/codeigniter4-relations?branch=develop)\n\n## Quick Start\n\n1. Install with Composer: `\u003e composer require tatter/relations`\n2. Add the trait to your model: `use \\Tatter\\Relations\\Traits\\ModelTrait`\n3. Load relations: `$users = $userModel-\u003ewith('groups')-\u003efindAll();`\n4. Add the trait to your entity: `use \\Tatter\\Relations\\Traits\\EntityTrait`\n5. Load relations: `foreach ($user-\u003egroups as $group)`\n\n(See also Examples at the bottom)\n\n## Installation\n\nInstall easily via Composer to take advantage of CodeIgniter 4's autoloading capabilities\nand always be up-to-date:\n```shell\n    \u003e composer require tatter/relations\n```\n\nOr, install manually by downloading the source files and adding the directory to\n**app/Config/Autoload.php***.\n\n## Configuration (optional)\n\nThe library's default behavior can be altered by extending its config file. Copy\n**examples/Relations.php** to **app/Config/** and follow the instructions\nin the comments. If no config file is found in **app/Config** the library will use its own.\n\n### Schemas\n\nAll the functionality of the library relies on the generated database schema. The schema comes from\n[Tatter\\Schemas](http://github.com/tattersoftware/codeigniter4-schemas) and can be adjusted\nbased on your needs (see the **Schemas** config file). If you want to use the auto-generated\nschema your database will have follow conventional naming patterns for foreign keys and\npivot/join tables; see [Tatter\\Schemas](http://github.com/tattersoftware/codeigniter4-schemas)\nfor details.\n\n## Usage\n\nRelation loading is handled by traits that are added to their respective elements.\n\n### Eager/Model\n\n**ModelTrait** adds relation loading to your models by extending the default model `find*`\nmethods and injecting relations into the returned results. Because this happens at the model\nlevel, related items can be loaded ahead of time in batches (\"eager loading\").\n\nAdd the trait to your models:\n```php\n\tuse \\Tatter\\Relations\\Traits\\ModelTrait\n```\n\nRelated items can be requested by adding a `$with` property to your model:\n```php\n\tprotected $with = 'groups';\n\t// or\n\tprotected $with = ['groups', 'permissions'];\n```\n\n... or by requesting it on-the-fly using the model `with()` method:\n\n```php\n$users = $userModel-\u003ewith('groups')-\u003efindAll();\nforeach ($users as $userEntity)\n{\n\techo \"User {$user-\u003ename} has \" . count($user-\u003egroups) . \" groups.\";\n...\n```\n\nAs you can see the related items are added directly to their corresponding object (or array)\nreturned from the framework's model.\n\n### Lazy/Entity\n\n**EntityTrait** adds relation loading to individual items by extending adding magic `__get()`\nand `__call()` methods to check for matching database tables. Because this happens on each\nitem, related items can be retrieved or updated on-the-fly (\"lazy loading\").\n\nAdd the trait and its necessary properties to your entities:\n```php\n\tuse \\Tatter\\Relations\\Traits\\EntityTrait\n\t\n\tprotected $table      = 'users';\n\tprotected $primaryKey = 'id';\n```\n\nRelated items are available as faux properties:\n```php\n\t$user = $userModel-\u003efind(1);\n\t\n\tforeach ($user-\u003egroups as $group)\n\t{\n\t\techo $group-\u003ename;\n\t}\n```\n\n... and can also be updated directly from the entity:\n```php\n\t$user-\u003eaddGroup(3);\n\t\n\tif ($user-\u003ehasGroups([1, 3]))\n\t{\n\t\techo 'allowed!';\n\t}\n\t\n\t$user-\u003esetGroups([]);\n```\n\nAvailable magic method verbs are: `has`, `set`, `add`, and `remove`, and are only applicable\nfor \"manyToMany\" relationships.\n\n## Returned items\n\n**Schemas** will attempt to associate your database tables back to their models, and if\nsuccessful, **Relations** will use each table's model to find the related items. This keeps\nconsistent the return types, events, and other aspects of your models. In addition to the\nreturn type, **Relations** will also adjust related items for singleton relationships:\n```php\n// User hasMany Widgets\n$user = $userModel-\u003ewith('widgets')-\u003efind($userId);\necho \"User {$user-\u003ename} has \" . count($user-\u003ewidgets) . \" widgets.\";\n\n// ... but a Widget belongsTo one User\n$widget = $widgetModel-\u003ewith('users')-\u003efind($widgetId);\necho $widget-\u003ename . \" belongs to \" . $widget-\u003euser-\u003ename;\n```\n\n### Nesting\n\n**ModelTrait** supports nested relation calls, but these can be resource intensive so may\nbe disabled by changing `$allowNesting` in the config. With nesting enabled, any related\nitems will also load their related items (but not infinitely):\n```php\n/* Define your models */\nclass UserModel\n{\n\tuse \\Tatter\\Relations\\Traits\\ModelTrait;\n\n\tprotected $table = 'users';\n\tprotected $with  = 'widgets';\n...\n\t\n/* Then in your controller */\n$groups = $groupModel-\u003ewhereIn('id', $groupIds)-\u003ewith('users')-\u003efindAll();\n\nforeach ($groups as $group)\n{\n\techo \"\u003ch1\u003e{$group-\u003ename}\u003c/h1\u003e\";\n\t\n\tforeach ($group-\u003eusers as $user)\n\t{\n\t\techo \"{$user-\u003ename} is a {$user-\u003erole} with \" . count($user-\u003ewidgets) . \" widgets.\";\n\t}\n}\n```\n\n### Soft Deletes\n\nIf your target relations correspond to a CodeIgniter Model that uses [soft deletion](https://codeigniter.com/user_guide/models/model.html#usesoftdeletes)\nthen you may include the table name in the `array $withDeletedRelations` property to include\nsoft deleted items. This is particularly helpful for tight relationships, like when an item\n`belongsTo` another item that has been soft deleted. `$withDeletedRelations` works on both\nEntities and Models.\n\n## Performance\n\n*WARNING*: Be aware that **Relations** relies on a schema generated from the **Schemas**\nlibrary. While this process is relatively quick, it will cause a noticeable delay if a page\nrequest initiates the load. The schema will attempt to cache to prevent this delay, but\nif your cache is not configured correctly you will likely experience noticeable performance\ndegradation. The recommended approach is to have a cron job generate your schema regularly\nso it never expires and no user will trigger the un-cached load, e.g.:\n```shell\nphp spark schemas\n```\n\nSee [Tatter\\Schemas](http://github.com/tattersoftware/codeigniter4-schemas) for more details.\n\n### Eager or Lazy Loading\n\nYou are responsible for your application's performance! These tools are here to help, but\nthey still allow dumb things.\n\nEager loading (via **ModelTrait**) can create a huge performance\nincrease by consolidating what would normally be multiple database calls into one. However,\nthe related items will take up additional memory and can cause other bottlenecks or script\nfailures if used indiscriminately.\n\nLazy loading (via **EntityTrait**) makes it very easy to work with related items only when\nthey are needed, and the magic functions keep your code clear and concise. However, each entity\nissues its own database call and can really start to slow down performance if used over\nover.\n\nA good rule of thumb is to use **ModelTrait** to preload relations that will be handled\nrepeatedly (e.g. in loops) or that represent a very small or static dataset (e.g. a set of\npreference strings from 10 available). Use **EntityTrait** to handle individual items, such\nas viewing a single user page, or when it is unlikely you will use relations for most of the\nitems.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftattersoftware%2Fcodeigniter4-relations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftattersoftware%2Fcodeigniter4-relations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftattersoftware%2Fcodeigniter4-relations/lists"}