PHPackages                             tkeer/flattable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. tkeer/flattable

ActiveLibrary[Database &amp; ORM](/categories/database)

tkeer/flattable
===============

Combine multiple tables in one flat god table.

v4.0(1y ago)92158[1 issues](https://github.com/tkeer/flattable/issues)MITPHPPHP ^8.0

Since Oct 6Pushed 1y ago5 watchersCompare

[ Source](https://github.com/tkeer/flattable)[ Packagist](https://packagist.org/packages/tkeer/flattable)[ RSS](/packages/tkeer-flattable/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (6)Versions (18)Used By (0)

[![laravel flattable](https://user-images.githubusercontent.com/20635376/95227830-06b9a880-0818-11eb-9681-5ee6dd569401.png)](https://user-images.githubusercontent.com/20635376/95227830-06b9a880-0818-11eb-9681-5ee6dd569401.png)

Laravel Flattable [![Build Status](https://camo.githubusercontent.com/9445623363badb6d3f1a281b7f1f56de3e9e13e3b3baad08a380762ea76dc0b6/68747470733a2f2f7472617669732d63692e6f72672f746b6565722f666c61747461626c652e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/tkeer/flattable) [![Build Status](https://camo.githubusercontent.com/faafec464786b4acb17f6a788169d0d2a5d47d7cd4d7d965f756763a3e9af24d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f746b6565722f666c61747461626c652e7376673f3f7374796c653d666c61742d737175617265)](https://packagist.org/packages/tkeer/flattable) [![Build Status](https://camo.githubusercontent.com/15e031f50f507654910762bef487d8ad6979cc1cf2ad406bea2057e7d0fc0fff/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f746b6565722f666c61747461626c652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/tkeer/flattable)
================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#laravel-flattable---)

It lets you manage de-normalized tables with simple configurations.

Just add array based config in your models and it will automatically sync your denormalized tables.

Introduction
------------

[](#introduction)

Do 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.

With flattable, you can combine multiple tables into one big table and improve performance by:

Minimizing the need for joins and subqueries, precomputing aggregate values, that is, computing them at data modification time, rather than at select time

[![laravel flattable](https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png)](https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png)

You just have to create a flat table, add configuration in related models, and everything will start working automatically.

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require tkeer/flattable
```

### Laravel version Compatibility

[](#laravel-version-compatibility)

LaravelPackage8.x|php83.x8.x|php72.x&lt;8.x1.xUsage
-----

[](#usage)

1. Add `Flattable` trait into your model
2. Implement `flattableConfig` method and add your configurations

Learn with examples
-------------------

[](#learn-with-examples)

It 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)

***Example DB structure***

1. We have books, publishers, countries tables
2. A book belongs to a publisher
3. A publisher belongs to a country

We want data of the book, book's publisher and country of the book's publisher in book's flattable (books\_flattable)

[![laravel flattable](https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png)](https://user-images.githubusercontent.com/20635376/95441979-3da4d100-0974-11eb-9855-1f902e1eb3df.png)

As 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).

To 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.

### 1. Book in book's flattable

[](#1-book-in-books-flattable)

> also updates/deletes when related book is updated or deleted

in `getFlattableConfig()` method of the `Book` model

```
public function getFlattableConfig(): array
{
  [
    [

      'columns' => [

        //flattable column => 'source model column'
        'name' => 'name',
        'published_at' => 'published_at',
        'publisher_id' => 'publisher_id',
        'book_id' => 'id'

      ],

      // type of relationship b/w flattable and model
      'type' => 'primary',

      // how to find related entry in the flattable table
      'wheres' => [

        // key is flattable column
        // value is column of source table (book)
        'book_id' => 'id',

      ],

      'flattable' => 'books_flattable',
    ]
  ]
}
```

### 2. Publisher in the book's flattable.

[](#2-publisher-in-the-books-flattable)

> it also updates flattable with new publisher when book's publisher is changed

Extend flattable config used above, and add config for publisher under `changes` key.

```
public function getFlattableConfig(): array
{
  [

    [

      'flattable' => 'books_flattable',
      ...

      'changes' => [

        // foreign colum name
        // we will update changes data only if this column is update(dirty)

        'publisher_id' => [

          'columns' => [

            'publisher_first_name' => 'first_name',
            'publisher_last_name' => 'last_name',

          ],

          // talbe name of the source
          'table' => 'publishers',
        ]
      ]
    ]
  ]
}
```

### 3. Country of the publisher in book's flattable

[](#3-country-of-the-publisher-in-books-flattable)

```
[
    //inside pubilsher config of books flattable
    ...
    'changes' => [
        'country_id' => [
            'columns' => [
                'publisher_country_name' => 'name',
                'publisher_country_id' => 'id',
            ],
            'where' => [
                'id' => 'country_id'
            ],
            'table' => 'countries'
        ]
    ]
]
```

you can go as many nested level as you want using `changes` attribute, ie `changes` attribute within `changes` attribute.

With 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.

What 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`.

See below

### Update book's flattable on publisher update

[](#update-books-flattable-on-publisher-update)

In `flattableConfig()` of the `Publisher` model

```
public function flattableConfig()
{
  return [
    [
      'columns' => [
          'publisher_first_name' => 'first_name',
          'publisher_last_name' => 'last_name',
      ],
      'wheres' => [
          'publisher_id' => 'id',
      ],
      'type' => 'secondary',

      'flattable' => 'books_flattable',
    ]
  ]
}
```

### Update book's flattable on country update

[](#update-books-flattable-on-country-update)

> Assigns null values to flattable when country is deleted

In `flattableConfig()` of the `Country` model

```
public function flattableConfig()
{
  return [
    [
      'columns' => [
          'publisher_country_name' => 'name',
          'publisher_country_id' => 'id',
      ],
      'wheres' => [
          'publisher_country_id' => 'id',
      ],
      'type' => 'secondary',

      'flattable' => 'books_flattable',
    ]
  ]
}
```

### Books in Publisher's flat table

[](#books-in-publishers-flat-table)

So far we have considered one-to-one relations, book belongs to one publisher, publisher belongs to one country.

What if there is one to many relationship between two tables.

For example, a publisher can have many books, and whenever any book is added, we want to add this book in the publisher's flattble.

[![](https://user-images.githubusercontent.com/20635376/95446814-426c8380-097a-11eb-893c-04017763af7c.png)](https://user-images.githubusercontent.com/20635376/95446814-426c8380-097a-11eb-893c-04017763af7c.png)

Add one more flattable config in `Book` model, the config `type` for this relation should be `many`.

```
public function flattableConfig(): array
{
  ...
  return [
            [
            'columns' => [
                'id' => 'id',
                'name' => 'name'
            ],

            // use type many when you want to store more than one entry in a column
            'type' => 'many',

            'wheres' => [
                'publisher_id' => 'publisher_id',
            ],
            //only delete from old if these keys have changed
            'delete_from_old_keys' => ['publisher_id'],

            'flattable' => 'publishers_flattable',

            // column name of the flaatable, in which the data should be stored.
            'flattable_column_name' => 'books',
        ]
  ]
}
```

Flattable config explanation
----------------------------

[](#flattable-config-explanation)

Flattable config has following attributes

[1. columns](#1-columns)

[2. wheres](#2-wheres)

[3. flattable](#3-flattable)

[4. changes](#4-changes)

[5. type](#5-type)

[6. flattable\_column\_name](#6-flattable_column_name)

[7. delete\_from\_old\_keys](#7-delete_from_old_keys)

[8. deletes\_primary](#8-deletes_primary)

#### 1. columns

[](#1-columns)

An array which holds the mapping of flattable columns and source table columns.

Each key in the columns array is the name of the flattable column, and the value is the name of source table column.

```
[
  'columns' => [
    'book_id' => 'id',
    'book_name' => 'name'
  ]
]
```

#### 2. wheres

[](#2-wheres)

An associate array of conditions to map related entry in the flattable.

The key in the sub-array is column name of the flattable and value is column name of the source table.

```
[
  'wheres' => [
    'book_id' => 'id'
  ]
]
```

#### 3. flattable

[](#3-flattable)

Name of the flattable.

#### 4. changes

[](#4-changes)

Include related tables data into the flattable. It should be an associate array.

The key of each array in the changes attribute should be the column name of the source table, whose change loads the related data in the flattable.

#### 5. type

[](#5-type)

It describes the relation type b/w flattable and source table

we have three types

##### 1. primary

[](#1-primary)

create, update, and delete do the same operation for the flattable.

For example, books relation with books\_flattable

##### 2. secondary

[](#2-secondary)

Same as primary, but deleting model will not delete the related entry in the flattable. Instead it will assign null values to the related columns in the flattable.

For example, publishers relationship with books\_flattable. If publisher of the book is deleted, then the publisher's attributes in the `books_flattable` will be set to `null`.

If you want entry in flattable to be delete for `secondary` type, set `deletes_primary` flag to `true`.

##### 3. many

[](#3-many)

For one to many relationship. With this type, we can store more than one entries in the flattable.

For example, books relationship with publishers\_flattable, one publisher can have more than one books.

### 6. flattable\_column\_name

[](#6-flattable_column_name)

Required when type is `many`. It holds the column name of the flattable, where json data will be stored.

### 7. delete\_from\_old\_keys

[](#7-delete_from_old_keys)

Required 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.

### 8. deletes\_primary

[](#8-deletes_primary)

primary `type` automaically deletes entry from the flattable, when entry from the main table is deleted, and secondary type store null values against related entries in flattable.

If you want that deleting an entry for secondary type also deletes related flattable entry, set `deletes_primary` flag to true.

Configurations
--------------

[](#configurations)

### Disable flattable a single model

[](#disable-flattable-a-single-model)

```
Book::disableFlattable();

$book = factory(Book::class)->create();
$bookFlattable = BookFlattable::where('book_id', $book->id)->first();
$this->assertNull($bookFlattable);

Book::enableFlattable();
```

### Disable flattable for all models

[](#disable-flattable-for-all-models)

Publish flattable config

```
php artisan vendor:publish --provider="Tkeer\Flattable\FlattableServiceProvider" --tag="config"
```

set `disabled` to `true` in `config/flattabe.php`

```
return [
    'console' => [
        'run' => true
    ],
    'disabled' => true
];
```

### Disable flattable for console

[](#disable-flattable-for-console)

You can optionally disable flattable when script is running through console,

To disable it set `console.run` to `false` in `config/flattable.php`.

### Using callbacks

[](#using-callbacks)

If none of available options works for your use case, you can pass a callback for `columns` and `wheres` configs.

For `columns` callback, you will receive model as parameter, and you should return data as array to be stored in flattable

```
[
  ...

  'columns' => function (Country $country) {
    // when secondary row is deleted, it's data should be removed from flattable
    return [
      'publisher_country_name' => $country->exists ? $country->name ? null,
      'publisher_country_id' => $country->exists ? $country->id ? null
    ];
  }

  ...
]
```

For `wheres` callback, you will receive `QueryBuilder` and `Model` as parameters, and you can add as many conditionals as you want.

```
[
  ...
  'wheres' => function (Builder $db, Country $model) {
    $db->where('publisher_country_id', $model->id);
  }

  ...
]
```

### Fill flattable

[](#fill-flattable)

You can use `flattable:fill` command to fill your flattable.

```
php artisan flattable:fill App\\Models\\Book
```

This command will use primary config of `Book` model and fill the related flattable

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance33

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~85 days

Recently: every ~341 days

Total

17

Last Release

679d ago

Major Versions

v1.0.5 → v2.1.02020-10-09

v1.1.0 → v2.1.12020-10-09

v1.1.1 → 2.x-dev2020-10-23

2.x-dev → v3.02021-12-31

v3.0 → v4.02024-07-04

PHP version history (4 changes)v2.0PHP ^7.3

v1.0PHP &gt;=7.1

v1.0.5PHP &gt;=7.0

v3.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/2963b3febf382bb84555aa913bfcba0a0c008189515c9f7e6d68e4baaf46627a?d=identicon)[tkeer](/maintainers/tkeer)

---

Top Contributors

[![tkeer](https://avatars.githubusercontent.com/u/20635376?v=4)](https://github.com/tkeer "tkeer (39 commits)")

---

Tags

denormalizationdenormalizedeloquentflattablelaravellaraveleloquentcombineflat tablegod

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/tkeer-flattable/health.svg)

```
[![Health](https://phpackages.com/badges/tkeer-flattable/health.svg)](https://phpackages.com/packages/tkeer-flattable)
```

###  Alternatives

[cviebrock/eloquent-sluggable

Easy creation of slugs for your Eloquent models in Laravel

4.0k13.6M253](/packages/cviebrock-eloquent-sluggable)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[cybercog/laravel-ban

Laravel Ban simplify blocking and banning Eloquent models.

1.1k651.8k11](/packages/cybercog-laravel-ban)[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
