PHPackages                             revaycolizer/data-display - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. revaycolizer/data-display

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

revaycolizer/data-display
=========================

The DataDisplay class is a dynamic PHP data table renderer built with Sweet Alert and Bootstrap. It supports adding, editing, deleting, searching, joining tables, and pagination — all from a fluent interface.

1.0.7(12mo ago)122MITPHP

Since Apr 25Pushed 12mo ago2 watchersCompare

[ Source](https://github.com/Revaycolizer/data-display)[ Packagist](https://packagist.org/packages/revaycolizer/data-display)[ RSS](/packages/revaycolizer-data-display/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (1)Versions (9)Used By (0)

### 📊 DataDisplay Component

[](#-datadisplay-component)

The DataDisplay class is a dynamic PHP data table renderer built with Sweet Alert and Bootstrap. It supports adding, editing, deleting, searching, joining tables, and pagination — all from a fluent interface.

### ✨ Features

[](#-features)

🗃 Dynamic table rendering with Bootstrap

🔍 Searchable columns with support for input/select types

### 🔐 CRUD Operations With Permissions

[](#-crud-operations-with-permissions)

### 🔄 Editable records with modals

[](#-editable-records-with-modals)

### ➕ Add new records using modals

[](#-add-new-records-using-modals)

### ❌ Delete functionality with confirmation

[](#-delete-functionality-with-confirmation)

### 🔗 Supports JOINs

[](#-supports-joins)

### 📑 Pagination support

[](#-pagination-support)

### 🔐 CSRF protection

[](#-csrf-protection)

### Instantiate the Component Using Doctrine For Data Fetching

[](#instantiate-the-component-using-doctrine-for-data-fetching)

```
use Revaycolizer\Crud\DataDisplay;

$dataTable = DataDisplay::create($entityManager, User::class);
```

### Instantiate the Component Using Classes For Data fetching

[](#instantiate-the-component-using-classes-for-data-fetching)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);
```

### Provide The Method Which Will be Used in Fetching Data When Using Classes

[](#provide-the-method-which-will-be-used-in-fetching-data-when-using-classes)

```
$dataDisplay
   ->setClassFetchDataFunction("all")
```

### Provide The Method With It's Parameters Which Will be Used in Fetching Data When Using Classes

[](#provide-the-method-with-its-parameters-which-will-be-used-in-fetching-data-when-using-classes)

```
$dataDisplay->setClassFetchDataFunction("all:param1,param2")
```

### DataDisplay Modes

[](#datadisplay-modes)

Mode 1: Default
---------------

[](#mode-1-default)

By Default the mode is Default There is no Need to Set Mode

```
->setMode(DataDisplayModes::DEFAULT)
```

Mode 2: Report
--------------

[](#mode-2-report)

If mode is set to report it will remove the CRUD Buttons(Add,Edit &amp; Delete)

```
 ->setMode(DataDisplayModes::REPORT)
```

### Action Button Modes

[](#action-button-modes)

Default
=======

[](#default)

```
  ->setActionsButtonMode(ActionsButtonMode::DEFAULT)
```

Dropdown
========

[](#dropdown)

```
  ->setActionsButtonMode(ActionsButtonMode::DROPDOWN)
```

### 🔧 Configuration

[](#-configuration)

Set Columns to Add

```
$dataTable->columnToBeAdded([
    'username' => ['type' => 'input', 'input_type' => 'text', 'label' => 'Username'],
    'role' => ['type' => 'select', 'label' => 'Role', 'options' => $roles, 'value_field' => 'id', 'label_field' => 'name']
]);
```

Set Columns to Edit

```
$dataTable->columnsToBeEdited([
    'username' => ['type' => 'input', 'input_type' => 'text'],
    'role' => ['type' => 'select', 'options' => $roles, 'value_field' => 'id', 'label_field' => 'name']
]);
```

Set Add Permission
------------------

[](#set-add-permission)

It takes a boolean value

```
$dataTable->setAddPermission(true);
```

Set Actions Button(Add,Edit,Delete)
-----------------------------------

[](#set-actions-buttonaddeditdelete)

By default All Buttons are enabled

```
use App\Types\Buttons;

$dataTable->setButtonsViewable([Buttons::VIEW,Buttons::EDIT]);
```

Add Action using Input
----------------------

[](#add-action-using-input)

```
$dataTable->setAddAction("Yooo")
```

Edit Action Using Input
-----------------------

[](#edit-action-using-input)

```
$dataTable->setEditAction("Yooo")
```

Delete Action
-------------

[](#delete-action)

```
$dataTable->setDeleteAction("Yooo")
```

SweetAlert Delete Title
-----------------------

[](#sweetalert-delete-title)

```
$dataTable->setDeleteTitle("Delete")
```

SweetAlert Delete Message
-------------------------

[](#sweetalert-delete-message)

```
 ->setDeleteMessage("Are you sure you want to delete this item?")
```

Set BootStrap Version
---------------------

[](#set-bootstrap-version)

By Default It uses BootStrap 5

```
use App\Types\Buttons;

$dataTable->setBootStrapVersion(BootStrap::V3)
```

Set SweetAlert Vision
---------------------

[](#set-sweetalert-vision)

By default it Uses SweetAlert 2

```
use App\Types\SweetAlert;

 $dataTable->setSweetAlertVersion(SweetAlert::V2)
```

For those Getting DataTable Initialization Error
------------------------------------------------

[](#for-those-getting-datatable-initialization-error)

```
$dataTable->setDelayDataTable(true)
```

set Datatable Buttons
---------------------

[](#set-datatable-buttons)

```
$dataTable->setDataTableButtons([
    'copy' => true,
    'csv' => ['title' => 'Exported CSV'],
    'excel' => ['title' => 'Excel Export'],
    'pdf' => [
        'title' => 'PDF Export',
        'orientation' => 'landscape',
        'pageSize' => 'A4',
    ],
    'print' => ['title' => 'Printable View'],
    'colvis' => ['text' => 'Toggle Columns'],
]);
```

Select Fields and JOINs
-----------------------

[](#select-fields-and-joins)

```
$dataTable->valuesToSelect([
    'e.id',
    'e.username',
    'r.name AS role_name'
])->tablesToJoin([
    ['table' => 'e.role', 'alias' => 'r', 'on' => 'e.role = r.id']
]);
```

Values to Render
----------------

[](#values-to-render)

If there are no Values to Render, it uses the Values to Select as a Fallback to render the items

```
 ->valuesToRender([
        "name",
        "price",
        "category_name"
    ])
```

### Edit Button Conditions

[](#edit-button-conditions)

You can decide to not specify the group operator which by default it will use AND operator as a fallback

```
    ->setEditButtonConditions([
        'conditions' => [
            ['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
            ['field' => 'price', 'operator' => '=', 'value' => '566'],
        ],
    ])
```

Specifying Group Operator
-------------------------

[](#specifying-group-operator)

```
    ->setEditButtonConditions([
        'conditions' => [
            ['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
            ['field' => 'price', 'operator' => '=', 'value' => '566'],
        ],
        'group_operator' => 'OR',
    ])
```

### How to Set Conditions:

[](#how-to-set-conditions)

Case 1: Simple OR condition (Conditions connected by OR):
---------------------------------------------------------

[](#case-1-simple-or-condition-conditions-connected-by-or)

```
->setEditButtonConditions([
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'OR',
])
```

This will return true if either name is equal to 'rrrooo' OR price is equal to 566.

Case 2: Simple AND condition (Conditions connected by AND):
-----------------------------------------------------------

[](#case-2-simple-and-condition-conditions-connected-by-and)

```
->setEditButtonConditions([
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'AND',
])
```

This will return true if both name is equal to 'rrrooo' AND price is equal to 566.

Case 3: Mixed AND and OR (More complex logic with groups):
----------------------------------------------------------

[](#case-3-mixed-and-and-or-more-complex-logic-with-groups)

```
->setEditButtonConditions([
'groups' => [
[
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'AND', // Conditions within this group are ANDed
],
[
'conditions' => [
['field' => 'stock', 'operator' => '>', 'value' => '100'],
['field' => 'category', 'operator' => '=', 'value' => 'Electronics'],
],
'group_operator' => 'OR', // Conditions within this group are ORed
],
],
'group_operator' => 'AND', // Groups themselves are ANDed together
])
```

This will evaluate like:

(name = 'rrrooo' AND price = '566')

OR

(stock &gt; 100 OR category = 'Electronics')

The overall result will be true if either the AND group (name and price) is true AND the OR group (stock or category) is true.

### Edit Callback Function

[](#edit-callback-function)

Instead of using setEditButtonCondition You can opt to use setEditButtonConditionCallback to provide your own callback

```
   ->setEditButtonConditionCallback(function ($row) {
        return $row['price'] > 500;
    })
```

### Delete Button Conditions

[](#delete-button-conditions)

You can decide to not specify the group operator which by default it will use AND operator as a fallback

```
    ->setDeleteButtonConditions([
        'conditions' => [
            ['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
            ['field' => 'price', 'operator' => '=', 'value' => '566'],
        ],
    ])
```

Specifying Group Operator
-------------------------

[](#specifying-group-operator-1)

```
    ->setDeleteButtonConditions([
        'conditions' => [
            ['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
            ['field' => 'price', 'operator' => '=', 'value' => '566'],
        ],
        'group_operator' => 'OR',
    ])
```

### How to Set Conditions:

[](#how-to-set-conditions-1)

Case 1: Simple OR condition (Conditions connected by OR):
---------------------------------------------------------

[](#case-1-simple-or-condition-conditions-connected-by-or-1)

```
->setDeleteButtonConditions([
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'OR',
])
```

This will return true if either name is equal to 'rrrooo' OR price is equal to 566.

Case 2: Simple AND condition (Conditions connected by AND):
-----------------------------------------------------------

[](#case-2-simple-and-condition-conditions-connected-by-and-1)

```
->setDeleteButtonConditions([
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'AND',
])
```

This will return true if both name is equal to 'rrrooo' AND price is equal to 566.

Case 3: Mixed AND and OR (More complex logic with groups):
----------------------------------------------------------

[](#case-3-mixed-and-and-or-more-complex-logic-with-groups-1)

```
->setDeleteButtonConditions([
'groups' => [
[
'conditions' => [
['field' => 'name', 'operator' => '=', 'value' => 'rrrooo'],
['field' => 'price', 'operator' => '=', 'value' => '566'],
],
'group_operator' => 'AND', // Conditions within this group are ANDed
],
[
'conditions' => [
['field' => 'stock', 'operator' => '>', 'value' => '100'],
['field' => 'category', 'operator' => '=', 'value' => 'Electronics'],
],
'group_operator' => 'OR', // Conditions within this group are ORed
],
],
'group_operator' => 'AND', // Groups themselves are ANDed together
])
```

This will evaluate like:

(name = 'rrrooo' AND price = '566')

OR

(stock &gt; 100 OR category = 'Electronics')

The overall result will be true if either the AND group (name and price) is true AND the OR group (stock or category) is true.

### Delete Callback Function

[](#delete-callback-function)

Instead of using setEditButtonCondition You can opt to use setEditButtonConditionCallback to provide your own callback

```
   ->setDeleteButtonConditionCallback(function ($row) {
        return $row['price'] > 500;
    })
```

### File Import and Template using Form Action

[](#file-import-and-template-using-form-action)

Import DownloadLabel and Import TemplateName are Optional

```
    ->setImportDownloadLabel("Download Template")
    ->setImportTemplateName("staff.xlsx")
    ->setImportColumns(
        [
            ['name' => 'Name', 'type' => 'string', 'required' => true],
            ['name' => 'Email', 'type' => 'string', 'required' => true],
            ['name' => 'Age', 'type' => 'integer', 'required' => false],
            ['name' => 'Date of Birth', 'type' => 'date', 'required' => false],
        ]
    )
    ->setCustomImportAction("/test")
```

### File Import and Template using Input Action

[](#file-import-and-template-using-input-action)

Import DownloadLabel and Import TemplateName are Optional

```
    ->setImportDownloadLabel("Download Template")
    ->setImportTemplateName("staff.xlsx")
    ->setImportColumns(
        [
            ['name' => 'Name', 'type' => 'string', 'required' => true],
            ['name' => 'Email', 'type' => 'string', 'required' => true],
            ['name' => 'Age', 'type' => 'integer', 'required' => false],
            ['name' => 'Date of Birth', 'type' => 'date', 'required' => false],
        ]
    )
    ->setImportAction("ImportStaff")
```

Custom Add Form
---------------

[](#custom-add-form)

```
->setCustomAddFormRenderer(function () {
        echo 'Custom Field';
    })
```

### Custom Add Form Header/Title

[](#custom-add-form-headertitle)

```
->setCustomAddFormHeader("Add New Category")
```

### Custom Edit Form

[](#custom-edit-form)

THe id Of Inputs Should have the datatable id passed eg dataTable\_editModalprice

Where dataTable is the id of datatable

```
->setCustomEditFormRenderer(function () {
    echo 'Custom Field';
})
```

### Custom Edit Form With Select

[](#custom-edit-form-with-select)

```
->setCustomEditFormRenderer(function () use ($categories) {
    echo '
        Product Name

      ';

    echo '
        Price ($)

      ';

    echo '
        Category

            -- Select Category --';
    foreach ($categories as $cat) {
        echo '' . htmlspecialchars($cat['name']) . '';
    }
    echo '
      ';
})
```

### Custom Edit Form Header/Title

[](#custom-edit-form-headertitle)

```
->setCustomEditFormHeader("Edit Category")
```

### Dialog Size

[](#dialog-size)

Add Dialog Size
---------------

[](#add-dialog-size)

```
->setAddDialogSize(DialogSizes::LARGE)
```

Edit Dialog Size
----------------

[](#edit-dialog-size)

```
->setEditDialogSize(DialogSizes::LARGE)
```

Actions button Mode
-------------------

[](#actions-button-mode)

DropDown
========

[](#dropdown-1)

```
 ->setActionsButtonMode(ActionsButtonMode::DROPDOWN)
```

Default
=======

[](#default-1)

```
->setActionsButtonMode(ActionsButtonMode::DEFAULT)
```

View Source Modes
-----------------

[](#view-source-modes)

Link
====

[](#link)

```
->setViewSource(ViewSource::LINK)
```

Modal
=====

[](#modal)

```
->setViewSource(ViewSource::MODAL)
```

Custom View Form Header
-----------------------

[](#custom-view-form-header)

```
 ->setCustomViewFormHeader("Image")
```

Values To Show On View Modal
----------------------------

[](#values-to-show-on-view-modal)

```
  ->setValuesToShowonModal([ "name" => [
        "type" => "input",
        "input_type" => "text",
        "label" => "Name",
    ],])
```

View Dialog Size
----------------

[](#view-dialog-size)

```
->setViewDialogSize(DialogSizes::LARGE)
```

Enable Search
-------------

[](#enable-search)

```
$dataTable->searchable([
    'e.username' => ['type' => 'input', 'label' => 'Username', 'column' => 'username'],
    'r.id' => ['type' => 'select', 'label' => 'Role', 'column' => 'id', 'options' => $roles, 'value_field' => 'id', 'label_field' => 'name']
]);
```

Custom Columns Before Actions Columns
-------------------------------------

[](#custom-columns-before-actions-columns)

```
 ->addColumnBeforeActions('Status Icon', fn($row) => $row['active'] ? '🟢' : '🔴')
```

Custom Columns Before Actions Columns Without Being Escaped
-----------------------------------------------------------

[](#custom-columns-before-actions-columns-without-being-escaped)

```
->addColumnBeforeActions('Role', fn($row) => "{$row['role']}", raw: true)
```

Custom Columns Before Actions Columns With Callback Visibility
--------------------------------------------------------------

[](#custom-columns-before-actions-columns-with-callback-visibility)

```
->addColumnBeforeActions(
    'Secret',
    fn($row) => '🔒 Secret!',
    raw: true,
    visibleWhen: fn($row) => $row['price'] > 1 && $row['name']==='RRR'
)
```

Custom Columns Before Actions Columns With Boolean Visibility
-------------------------------------------------------------

[](#custom-columns-before-actions-columns-with-boolean-visibility)

```
->addColumnAfterActions(
    'Secret Info',
    fn($row) => '🔒 Secret!',
    raw: true,
    visibleWhen: fn($row) => true
)
```

Custom Columns After Actions Columns
------------------------------------

[](#custom-columns-after-actions-columns)

```
 ->addColumnAfterActions('Status Icon', fn($row) => $row['active'] ? '🟢' : '🔴')
```

Custom Columns After Actions Columns Without Being Escaped
----------------------------------------------------------

[](#custom-columns-after-actions-columns-without-being-escaped)

```
->addColumnAfterActions('Role', fn($row) => "{$row['role']}", raw: true)
```

Custom Columns After Actions Columns With Callback Visibility
-------------------------------------------------------------

[](#custom-columns-after-actions-columns-with-callback-visibility)

```
->addColumnAfterActions(
    'Secret',
    fn($row) => '🔒 Secret!',
    raw: true,
    visibleWhen: fn($row) => $row['price'] > 1 && $row['name']==='RRR'
)
```

Custom Columns After Actions Columns With Boolean Visibility
------------------------------------------------------------

[](#custom-columns-after-actions-columns-with-boolean-visibility)

```
->addColumnAfterActions(
    'Secret Info',
    fn($row) => '🔒 Secret!',
    raw: true,
    visibleWhen: fn($row) => true
)
```

Data Transformation
-------------------

[](#data-transformation)

```
->setRowDataTransformer(function($row) {
    if (!empty($row['id'])) {
        $row['name'] = strtoupper($row['name']);
        $row['role'] = strtoupper($row['name']);
    }

    if($row['price']>600){
        $row['active'] =true;
    }
    $row['total_price'] = $row['price'] +1;
    return $row;
})
```

Enable Pagination
-----------------

[](#enable-pagination)

```
$dataTable->enablePagination(10, ['username', 'role']);
```

🖥 Rendering the Table
---------------------

[](#-rendering-the-table)

```
$dataTable->renderDataTable($_GET['page'] ?? 1);
```

🧼 Handling Form Submissions
---------------------------

[](#-handling-form-submissions)

```
    $dataTable->handleRequest($_POST ?? []);
```

### ✅ Example a Simple Workflow Without Joins

[](#-example-a-simple-workflow-without-joins)

Columns to add and Columns to Edit support using both associative and indexed array

```
$dataDisplay = DataDisplay::create($entityManager, User::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name"])
    ->columnToBeAdded([
     "name"
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ]);

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Add Permission

[](#-example-a-simple-workflow-with-add-permission)

```
$dataDisplay = DataDisplay::create($entityManager, User::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name"])
    ->columnToBeAdded([
     "name"
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setAddPermission(true)
    ->setDataTableButtons([
        'copy' => true,
        'csv' => true,
        'excel' => ['title' => 'Excel Export'],
        'pdf' => [
            'title' => 'PDF Export',
            'orientation' => 'landscape',
            'pageSize' => 'A4',
        ],
        'print' => ['title' => 'Printable View'],
        'colvis' => ['text' => 'Toggle Columns'],
    ]);
```

### ✅ Example a Simple Workflow With Datatable Buttons

[](#-example-a-simple-workflow-with-datatable-buttons)

```
$dataDisplay = DataDisplay::create($entityManager, User::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name"])
    ->columnToBeAdded([
     "name"
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setDataTableButtons([
        'copy' => true,
        'csv' => true,
        'excel' => ['title' => 'Excel Export'],
        'pdf' => [
            'title' => 'PDF Export',
            'orientation' => 'landscape',
            'pageSize' => 'A4',
        ],
        'print' => ['title' => 'Printable View'],
        'colvis' => ['text' => 'Toggle Columns'],
    ]);
```

### ✅ Example a Simple Workflow With Custom Add and Edit Form

[](#-example-a-simple-workflow-with-custom-add-and-edit-form)

```
$dataDisplay = DataDisplay::create($entityManager, User::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name"])
    ->columnToBeAdded([
     "name"
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setAddPermission(true)
    ->setCustomAddFormRenderer(function () {
        echo 'Custom Field';
    })
    ->setCustomEditFormRenderer(function () {
        echo 'Custom Field';
    })
    ->setDataTableButtons([
        'copy' => true,
        'csv' => true,
        'excel' => ['title' => 'Excel Export'],
        'pdf' => [
            'title' => 'PDF Export',
            'orientation' => 'landscape',
            'pageSize' => 'A4',
        ],
        'print' => ['title' => 'Printable View'],
        'colvis' => ['text' => 'Toggle Columns'],
    ]);

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Joins and Search Functionality

[](#-example-a-simple-workflow-with-joins-and-search-functionality)

```
$categories = Category::getAllCategories($entityManager) ?? [];

$dataDisplay = DataDisplay::create($entityManager, Product::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name", "e.price", "c.name AS category_name"])
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => "Price",
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->enablePagination(10, ["e.name", "e.id"])
    ->searchable([
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "operator" => "=",
            "table" => "e",
            "column" => "category_id",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])

    ->setAddButtonLabel("Create New Product")
    ->setTableId("dataTable")
    ->tablesToJoin([
        [
            "table" => "Category::class",
            "alias" => "c",
            "on" => "e.category_id = c.id",
        ],
    ]);

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Custom Add and Edit Form

[](#-example-a-simple-workflow-with-custom-add-and-edit-form-1)

```
$categories = Category::getAllCategories($entityManager) ?? [];

$dataDisplay = DataDisplay::create($entityManager, Product::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name", "e.price","e.category_id", "c.name AS category_name"])
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => "Price",
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category 1",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->valuesToRender([
        "id",
        "name",
        "price",
        "category_name"
    ])
    ->setCustomAddFormHeader("Add New Category")
    ->setCustomEditFormHeader("Edit Category")
    ->setCustomEditFormRenderer(function () use ($categories) {
        echo '
            Product Name

          ';

        echo '
            Price ($)

          ';

        echo '
            Category

                -- Select Category --';
        foreach ($categories as $cat) {
            echo '' . htmlspecialchars($cat['name']) . '';
        }
        echo '
          ';
    })

    ->setEditButtonConditionCallback(function ($row) {
        return $row['price'] > 100;
    })

    ->searchable([
        "category" => [
            "type" => "select",
            "label" => "Category",
            "operator" => "=",
            "table" => "e",
            "column" => "category_id",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])

    ->setAddButtonLabel("Create New Product")
    ->setTableId("dataTable")
    ->tablesToJoin([
        [
            "table" => Category::class,
            "alias" => "c",
            "on" => "e.category_id = c.id",
        ],
    ])
    ->setDataTableButtons([
        'copy' => true,
        'csv' => ['title' => 'Exported CSV'],
        'excel' => ['title' => 'Excel Export'],
        'pdf' => [
            'title' => 'PDF Export',
            'orientation' => 'landscape',
            'pageSize' => 'A4',
        ],
        'print' => ['title' => 'Printable View'],
        'colvis' => ['text' => 'Toggle Columns'],
    ]);

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Data Transformation,Joins and Custom Columns

[](#-example-a-simple-workflow-with-data-transformationjoins-and-custom-columns)

```
$categories = Category::getAllCategories($entityManager) ?? [];

$dataDisplay = DataDisplay::create($entityManager, Product::class);

$dataDisplay
    ->valuesToSelect(["e.id", "e.name", "e.price","e.category_id", "c.name AS category_name"])
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => "Price",
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category 1",
            "options" => $categories,
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->valuesToRender([
        "id",
        "name",
        "price",
        "category_name"
    ])
    ->setRowDataTransformer(function($row) {
        if (!empty($row['id'])) {
            $row['name'] = strtoupper($row['name']);
            $row['role'] = strtoupper($row['name']);
        }

        if($row['price']>600){
            $row['active'] =true;
        }
        $row['total_price'] = $row['price'] +1;
        return $row;
    })
    ->addColumnAfterActions('Status Icon', fn($row) => $row['active'] ? '🟢' : '🔴')
    ->addColumnBeforeActions('Role', fn($row) => "{$row['role']}", raw: true)
    ->addColumnAfterActions(
        'Secret Info',
        fn($row) => '🔒 Secret!',
        raw: true,
        visibleWhen: fn($row) => true
    )
    ->addColumnAfterActions(
        'Secret',
        fn($row) => '🔒 Secret!',
        raw: true,
        visibleWhen: fn($row) => $row['price'] > 1 && $row['name']==='RRR'
    )
    ->tablesToJoin([
        [
            "table" => Category::class,
            "alias" => "c",
            "on" => "e.category_id = c.id",
        ],
    ]);
```

### ✅ Example a Simple Workflow With Classes For Data Fetching

[](#-example-a-simple-workflow-with-classes-for-data-fetching)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
   ->setClassFetchDataFunction("all")
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ;

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Report Mode

[](#-example-a-simple-workflow-with-report-mode)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
   ->setClassFetchDataFunction("all")
    ->setMode(DataDisplayModes::REPORT)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin")
    ;

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Dialog Size

[](#-example-a-simple-workflow-with-dialog-size)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
   ->setClassFetchDataFunction("all")
   ->setAddDialogSize(DialogSizes::LARGE)
   ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin")
    ;

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Action Buttons in Dropdown Mode

[](#-example-a-simple-workflow-with-action-buttons-in-dropdown-mode)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
    ->setClassFetchDataFunction("all")
    ->setAddDialogSize(DialogSizes::LARGE)
    ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => [],
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setActionsButtonMode(ActionsButtonMode::DROPDOWN)
    ->valuesToRender(["id", "name"])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin");
```

### ✅ Example a Simple Workflow With View Source(Modal) and Action Button Modes(DropDown)

[](#-example-a-simple-workflow-with-view-sourcemodal-and-action-button-modesdropdown)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
    ->setClassFetchDataFunction("all")
    ->setAddDialogSize(DialogSizes::LARGE)
    ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => [],
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
    ->setActionsButtonMode(ActionsButtonMode::DROPDOWN)
    ->setViewSource(ViewSource::MODAL)
    ->setViewDialogSize(DialogSizes::LARGE)
    ->setCustomViewFormHeader("Image")
    ->setValuesToShowonModal([ "name" => [
        "type" => "input",
        "input_type" => "text",
        "label" => "Name",
    ],])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin");

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With View Source(Link) and Action Button Modes(Default)

[](#-example-a-simple-workflow-with-view-sourcelink-and-action-button-modesdefault)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
    ->setClassFetchDataFunction("all")
    ->setAddDialogSize(DialogSizes::LARGE)
    ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => [],
            "value_field" => "id",
            "label_field" => "name",
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
        ],
    ])
     ->setViewLink("/test=")
    ->setViewDialogSize(DialogSizes::LARGE)
    ->setCustomViewFormHeader("Image")
    ->setValuesToShowonModal([ "name" => [
        "type" => "input",
        "input_type" => "text",
        "label" => "Name",
        "required" => true,
    ],])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
            "required" => true,
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
            "required" => true,
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin");

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Delete Conditions

[](#-example-a-simple-workflow-with-delete-conditions)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
    ->setClassFetchDataFunction("all")
    ->setAddDialogSize(DialogSizes::LARGE)
    ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
            "required" => true,
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
            "required" => true,
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => [],
            "value_field" => "id",
            "label_field" => "name",
            "required" => true,
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
            "required" => true,
        ],
    ])
    ->setViewLink("/test/")
    ->setViewDialogSize(DialogSizes::LARGE)
    ->setCustomViewFormHeader("Image")
    ->setValuesToShowonModal([ "name" => [
        "type" => "input",
        "input_type" => "text",
        "label" => "Name",
    ],])

     ->setDeleteButtonConditions([
        'conditions' => [
            ['field' => 'name', 'operator' => '=', 'value' => 'Books'],
        ],
    ])
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
            "required" => true,
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
            "required" => true,
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin");

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

### ✅ Example a Simple Workflow With Delete Callback

[](#-example-a-simple-workflow-with-delete-callback)

```
$dataDisplay = DataDisplay::create(null, Category::class,DataSourceType::CLASSES);

$dataDisplay
    ->setClassFetchDataFunction("all")
    ->setAddDialogSize(DialogSizes::LARGE)
    ->setEditDialogSize(DialogSizes::LARGE)
    ->columnToBeAdded([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
            "required" => true,
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
            "required" => true,
        ],
        "category_id" => [
            "type" => "select",
            "label" => "Category",
            "options" => [],
            "value_field" => "id",
            "label_field" => "name",
            "required" => true,
        ],
    ])
    ->columnsToBeEdited([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Name",
            "required" => true,
        ],
    ])

    ->setViewLink("/test/")
    ->setViewDialogSize(DialogSizes::LARGE)
    ->setCustomViewFormHeader("Image")
    ->setValuesToShowonModal([ "name" => [
        "type" => "input",
        "input_type" => "text",
        "label" => "Name",
    ],])

    ->setDeleteButtonConditionCallback(function ($row) {
        return $row["name"] !== 'Books';
    })
    ->valuesToRender(["id", "name"])
    ->searchable([
        "name" => [
            "type" => "input",
            "input_type" => "text",
            "label" => "Product Name",
        ],
        "price" => [
            "type" => "input",
            "input_type" => "number",
            "label" => 'Price ($)',
        ],
    ])
    ->setCustomAddAction("/test")
    ->setCustomEditAction("/admin");

$dataDisplay->handleRequest($_POST ?? []);
$dataDisplay->renderDataTable();
```

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance50

Moderate activity, may be stable

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 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 ~3 days

Total

8

Last Release

363d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/70aaf7194f085004bc48bffd59f828c0b0690786048ca8ef5a0395e1d25bf72d?d=identicon)[Revaycolizer](/maintainers/Revaycolizer)

---

Top Contributors

[![Revaycolizer](https://avatars.githubusercontent.com/u/109684996?v=4)](https://github.com/Revaycolizer "Revaycolizer (34 commits)")

### Embed Badge

![Health badge](/badges/revaycolizer-data-display/health.svg)

```
[![Health](https://phpackages.com/badges/revaycolizer-data-display/health.svg)](https://phpackages.com/packages/revaycolizer-data-display)
```

###  Alternatives

[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k20](/packages/civicrm-civicrm-core)[in2code/powermail

Powermail is a well-known, editor-friendly, powerful and easy to use mailform extension for TYPO3 with a lots of features

982.5M38](/packages/in2code-powermail)[blair2004/nexopos

The Free Modern Point Of Sale System build with Laravel, TailwindCSS and Vue.js.

1.2k2.3k](/packages/blair2004-nexopos)[solspace/craft-freeform

The most flexible and user-friendly form building plugin!

52664.9k12](/packages/solspace-craft-freeform)[pimcore/data-importer

Adds a comprehensive import functionality to Pimcore Datahub

44763.4k2](/packages/pimcore-data-importer)[portphp/spreadsheet

PhpSpreadsheet reader and writer for Port

14796.4k4](/packages/portphp-spreadsheet)

PHPackages © 2026

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