{"id":33944222,"url":"https://github.com/tkeer/flattable","last_synced_at":"2026-04-05T11:31:49.804Z","repository":{"id":57070398,"uuid":"301171551","full_name":"tkeer/flattable","owner":"tkeer","description":"It helps you manage de-normalized tables","archived":false,"fork":false,"pushed_at":"2024-07-04T18:58:42.000Z","size":118,"stargazers_count":92,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-12-14T05:42:20.108Z","etag":null,"topics":["denormalization","denormalized","eloquent","flattable","laravel"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tkeer.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-04T16:15:07.000Z","updated_at":"2025-09-30T10:22:45.000Z","dependencies_parsed_at":"2022-08-24T14:54:22.296Z","dependency_job_id":null,"html_url":"https://github.com/tkeer/flattable","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/tkeer/flattable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkeer%2Fflattable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkeer%2Fflattable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkeer%2Fflattable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkeer%2Fflattable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkeer","download_url":"https://codeload.github.com/tkeer/flattable/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkeer%2Fflattable/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31434624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["denormalization","denormalized","eloquent","flattable","laravel"],"created_at":"2025-12-12T17:04:14.298Z","updated_at":"2026-04-05T11:31:49.795Z","avatar_url":"https://github.com/tkeer.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\n\u003cimg src=\"https://user-images.githubusercontent.com/20635376/95227830-06b9a880-0818-11eb-9681-5ee6dd569401.png\" alt=\"laravel flattable\"\u003e\n\u003c/p\u003e\n\n\nLaravel Flattable [![Build Status](https://travis-ci.org/tkeer/flattable.svg?branch=master)](https://travis-ci.org/tkeer/flattable) [![Build Status](https://img.shields.io/packagist/v/tkeer/flattable.svg??style=flat-square)](https://packagist.org/packages/tkeer/flattable) [![Build Status](https://img.shields.io/packagist/l/tkeer/flattable.svg?style=flat-square)](https://packagist.org/packages/tkeer/flattable)\n===============\n\n\nIt lets you manage de-normalized tables with simple \nconfigurations.\n\nJust add array based config in your models and it will\nautomatically sync your denormalized tables. \n\n\nIntroduction\n----------\n\nDo you currenlty have de-normalized tables in your laravel application, or planning to have one, this package can help you keep your denormalized tables synced with source tables.\n\nWith flattable, you can combine multiple tables into one big table and improve performance by:\n\nMinimizing the need for joins and subqueries, precomputing aggregate values, that is, computing them at data modification time, rather than at select time\n\n\u003cp\u003e\n\n\u003cimg height=\"300px\" src=\"https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png\" alt=\"laravel flattable\"\u003e\n\u003c/p\u003e\n\n\nYou just have to create a flat table, add configuration in related models,\nand everything will start working automatically.\n\n\nInstallation\n------------\nInstall the package via Composer:\n\n```bash\ncomposer require tkeer/flattable\n```\n\n### Laravel version Compatibility\n Laravel  | Package\n:---------|:----------\n 8.x\\|php8      | 3.x\n 8.x\\|php7      | 2.x\n \u003c8.x          | 1.x\n\nUsage\n------------\n1. Add `Flattable` trait into your model\n2. Implement `flattableConfig` method and add your configurations\n\nLearn with examples\n-------\n\nIt is easier to explain it with the help of examples. For more detailed examples, please review the [tests](https://github.com/tkeer/flattable/tree/master/tests)\n\n\n***Example DB structure***\n\n1. We have books, publishers, countries tables\n2. A book belongs to a publisher\n3. A publisher belongs to a country\n\n\nWe want data of the book, book's publisher and country of the book's publisher in book's flattable (books_flattable)\n\n\u003cimg height=\"300px\" src=\"https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png\" alt=\"laravel flattable\"\u003e\n\nAs book is main table here, we will add flattable configuration in the book's model, and the `type` should be `primary`, more on type [here](#5-type).\n\nTo explain the problem, we will break our configurations into 3 parts. For detailed configuration for the book, please see first config entry of [book](https://github.com/tkeer/flattable/blob/master/tests/Models/Book.php#L22)'s model in tests.\n\n### 1. Book in book's flattable\n\u003e also updates/deletes when related book is updated or deleted\n\nin `getFlattableConfig()` method of the `Book` model\n\n```php\npublic function getFlattableConfig(): array\n{\n  [\n    [\n\n      'columns' =\u003e [\n\n        //flattable column =\u003e 'source model column'\n        'name' =\u003e 'name',\n        'published_at' =\u003e 'published_at',\n        'publisher_id' =\u003e 'publisher_id',\n        'book_id' =\u003e 'id'\n\n      ],\n\n      // type of relationship b/w flattable and model\n      'type' =\u003e 'primary',\n\n      // how to find related entry in the flattable table\n      'wheres' =\u003e [\n\n        // key is flattable column\n        // value is column of source table (book)\n        'book_id' =\u003e 'id',\n\n      ],\n\n      'flattable' =\u003e 'books_flattable',\n    ]\n  ]\n}\n```\n\n### 2. Publisher in the book's flattable.\n\u003e it also updates flattable with new publisher when book's publisher is changed\n\nExtend flattable config used above, and add config for publisher under `changes` key.\n\n```php\npublic function getFlattableConfig(): array\n{\n  [\n\n    [\n\n      'flattable' =\u003e 'books_flattable',\n      ...\n\n      'changes' =\u003e [\n\n        // foreign colum name\n        // we will update changes data only if this column is update(dirty)\n\n        'publisher_id' =\u003e [\n\n          'columns' =\u003e [\n\n            'publisher_first_name' =\u003e 'first_name',\n            'publisher_last_name' =\u003e 'last_name',\n\n          ],   \n\n          // talbe name of the source\n          'table' =\u003e 'publishers',\n        ]\n      ]\n    ]\n  ]\n}\n\n```\n\n### 3. Country of the publisher in book's flattable\n\n```php\n[\n    //inside pubilsher config of books flattable\n    ...\n    'changes' =\u003e [\n        'country_id' =\u003e [\n            'columns' =\u003e [\n                'publisher_country_name' =\u003e 'name',\n                'publisher_country_id' =\u003e 'id',\n            ],\n            'where' =\u003e [\n                'id' =\u003e 'country_id'\n            ],\n            'table' =\u003e 'countries'\n        ]\n    ]\n]\n```\n\nyou can go as many nested level as you want using `changes` attribute, ie `changes` attribute within `changes` attribute.\n\n\nWith added configuration so far, any change in the book will automatically update the book's flattable. Even if the publisher of the book is changed, the flattable will automatically be updated with new publisher data.\n\nWhat if publisher itself is updated, ie first_name of the publisher is updated, or the country of publisher is updated. For this we have to implement flattable for the `Publisher` and `Country` models and add flattable config in both models, and the config `type` should be `secondary`.\n\nSee below\n\n### Update book's flattable on publisher update\n\nIn `flattableConfig()` of the `Publisher` model\n\n```php\npublic function flattableConfig()\n{\n  return [\n    [\n      'columns' =\u003e [\n          'publisher_first_name' =\u003e 'first_name',\n          'publisher_last_name' =\u003e 'last_name',\n      ],\n      'wheres' =\u003e [\n          'publisher_id' =\u003e 'id',\n      ],\n      'type' =\u003e 'secondary',\n\n      'flattable' =\u003e 'books_flattable',\n    ]\n  ]\n}\n```\n\n### Update book's flattable on country update\n\u003e Assigns null values to flattable when country is deleted\n\nIn `flattableConfig()` of the `Country` model\n\n```php\npublic function flattableConfig()\n{\n  return [\n    [\n      'columns' =\u003e [\n          'publisher_country_name' =\u003e 'name',\n          'publisher_country_id' =\u003e 'id',\n      ],\n      'wheres' =\u003e [\n          'publisher_country_id' =\u003e 'id',\n      ],\n      'type' =\u003e 'secondary',\n\n      'flattable' =\u003e 'books_flattable',\n    ]\n  ]\n}\n```\n\n\n### Books in Publisher's flat table\n\nSo far we have considered one-to-one relations, book belongs to one publisher, publisher belongs to one country.\n\nWhat if there is one to many relationship between two tables.\n\nFor example, a publisher can have many books, and whenever any book is added, we want to add this book in the publisher's flattble. \n\n\u003cimg height=\"300px\" src=\"https://user-images.githubusercontent.com/20635376/95446814-426c8380-097a-11eb-893c-04017763af7c.png\"\u003e\n\n\nAdd one more flattable config in `Book` model, the config `type` for this relation should be `many`.\n\n\n```php\npublic function flattableConfig(): array\n{\n  ...\n  return [\n            [\n            'columns' =\u003e [\n                'id' =\u003e 'id',\n                'name' =\u003e 'name'\n            ],\n\n            // use type many when you want to store more than one entry in a column\n            'type' =\u003e 'many',\n\n            'wheres' =\u003e [\n                'publisher_id' =\u003e 'publisher_id',\n            ],\n            //only delete from old if these keys have changed\n            'delete_from_old_keys' =\u003e ['publisher_id'],\n\n            'flattable' =\u003e 'publishers_flattable',\n\n            // column name of the flaatable, in which the data should be stored.\n            'flattable_column_name' =\u003e 'books',\n        ]\n  ]\n}\n\n```\n\n\nFlattable config explanation\n-------------\n\nFlattable config has following attributes\n\n[1. columns](#1-columns)\n\n[2. wheres](#2-wheres)\n\n[3. flattable](#3-flattable)\n\n[4. changes](#4-changes)\n\n[5. type](#5-type)\n\n[6. flattable_column_name](#6-flattable_column_name)\n\n[7. delete_from_old_keys](#7-delete_from_old_keys)\n\n[8. deletes_primary](#8-deletes_primary)\n\n#### 1. columns\n\nAn array which holds the mapping of flattable columns and source table columns.\n\nEach key in the columns array is the name of the flattable column, and the value is the name of source table column.\n\n```php\n[\n  'columns' =\u003e [\n    'book_id' =\u003e 'id',\n    'book_name' =\u003e 'name'\n  ]\n]\n```\n#### 2. wheres\n\nAn associate array of conditions to map related entry in the flattable.\n\nThe key in the sub-array is column name of the flattable and value is column name of the source table.\n\n```php\n[\n  'wheres' =\u003e [\n    'book_id' =\u003e 'id'\n  ]\n]\n```\n\n#### 3. flattable\n\nName of the flattable.\n\n#### 4. changes\n\nInclude related tables data into the flattable. It should be an associate array.\n\nThe key of each array in the changes attribute should be the column name of the source table, whose change loads\nthe related data in the flattable.\n\n#### 5. type\n\nIt describes the relation type b/w flattable and source table\n\nwe have three types\n\n##### 1. primary\n\ncreate, update, and delete do the same operation\nfor the flattable.\n\nFor example, books relation with books_flattable\n\n##### 2. secondary\n\nSame as primary, but deleting model will not delete the related entry in the flattable.\nInstead it will assign null values to the related columns in the flattable.\n\nFor example, publishers relationship with books_flattable. \nIf publisher of the book is deleted, then the publisher's attributes\nin the `books_flattable` will be set to `null`.\n\nIf you want entry in flattable to be delete for \n`secondary` type, set `deletes_primary` flag to `true`.\n\n##### 3. many\n\nFor one to many relationship. With this type, we can store more than one entries\n in the flattable.\n\nFor example, books relationship with publishers_flattable, one publisher can have more than one\nbooks.\n\n### 6. flattable_column_name\nRequired when type is `many`. It holds the column name of the flattable, where json data will be stored.\n\n### 7. delete_from_old_keys\nRequired when type is `many`. It holds the names of columns, any change in these columns will reload the related json data of related flattable column.\n\n### 8. deletes_primary\nprimary `type` automaically deletes entry from the flattable, when entry from the main table is deleted, and\nsecondary type store null values against related entries in flattable.\n\nIf you want that deleting an entry for secondary type also deletes related\nflattable entry, set `deletes_primary` flag to true.\n\nConfigurations\n--------------\n### Disable flattable a single model\n```php\nBook::disableFlattable();\n\n$book = factory(Book::class)-\u003ecreate();\n$bookFlattable = BookFlattable::where('book_id', $book-\u003eid)-\u003efirst();\n$this-\u003eassertNull($bookFlattable);\n\nBook::enableFlattable();\n```\n\n### Disable flattable for all models\n\nPublish flattable config\n```shell script\nphp artisan vendor:publish --provider=\"Tkeer\\Flattable\\FlattableServiceProvider\" --tag=\"config\"\n```\nset `disabled` to `true` in `config/flattabe.php`\n\n```php\nreturn [\n    'console' =\u003e [\n        'run' =\u003e true\n    ],\n    'disabled' =\u003e true\n];\n```\n\n### Disable flattable for console\n\nYou can optionally disable flattable when script is \nrunning through console,\n\nTo disable it set `console.run` to `false` in `config/flattable.php`.\n\n\n### Using callbacks\nIf none of available options works for your use case, you can pass a callback for `columns` and `wheres` configs.\n\nFor `columns` callback, you will receive model as parameter, and you should return data as array to be stored in flattable\n\n```php\n[\n  ...\n\n  'columns' =\u003e function (Country $country) {\n    // when secondary row is deleted, it's data should be removed from flattable\n    return [\n      'publisher_country_name' =\u003e $country-\u003eexists ? $country-\u003ename ? null,\n      'publisher_country_id' =\u003e $country-\u003eexists ? $country-\u003eid ? null\n    ];\n  }\n\n  ...\n]\n```\n\nFor `wheres` callback, you will receive `QueryBuilder` and `Model` as parameters, and you can add as many conditionals as you want. \n```php\n[\n  ...\n  'wheres' =\u003e function (Builder $db, Country $model) {\n    $db-\u003ewhere('publisher_country_id', $model-\u003eid);\n  }\n\n  ...\n]\n\n```\n\n### Fill flattable\n\nYou can use `flattable:fill` command to fill your flattable. \n\n```shell script\nphp artisan flattable:fill App\\\\Models\\\\Book\n```\n\nThis command will use primary config of `Book` model\nand fill the related flattable\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkeer%2Fflattable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkeer%2Fflattable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkeer%2Fflattable/lists"}