PHPackages                             phpbootstraptableedit/phpbootstraptableedit - 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. phpbootstraptableedit/phpbootstraptableedit

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

phpbootstraptableedit/phpbootstraptableedit
===========================================

Database table editor, datagrid, themed with Bootstrap css

0.0.8(1y ago)3364MITPHPPHP &gt;=7.0.0

Since Apr 14Pushed 1y ago1 watchersCompare

[ Source](https://github.com/PHPBootstrapTableEdit/PHPBootstrapTableEdit)[ Packagist](https://packagist.org/packages/phpbootstraptableedit/phpbootstraptableedit)[ RSS](/packages/phpbootstraptableedit-phpbootstraptableedit/feed)WikiDiscussions master Synced 4w ago

READMEChangelogDependenciesVersions (9)Used By (0)

PHP Bootstrap Table Edit - datagrid library to edit database tables
===================================================================

[](#php-bootstrap-table-edit---datagrid-library-to-edit-database-tables)

- Define table, forms, and inputs using SQL statements
- Search, column sorting, pagination, no javascript required
- File and image uploads to filesystem or into database field (blob)
- No built-in validation, instead it's encouraged to use HTML's *pattern* attribute, and the *required* property
- Hooks available to add validation, format data, or run code, on or after: inserts, updates, and deletes
- Styled with Bootstrap css framework

License
-------

[](#license)

MIT

Screenshots
-----------

[](#screenshots)

[![index](screenshots/index.gif)](screenshots/index.gif)[![edit](screenshots/edit.gif)](screenshots/edit.gif)

Requirements
------------

[](#requirements)

- PHP 7+ with mbstring and gd extensions enabled
- SQLite 3, MariaDB/MySQL, or PostgreSQL

Status
------

[](#status)

This project is currently beta

Quick demo using SQLite3 and PHP's built-in webserver
-----------------------------------------------------

[](#quick-demo-using-sqlite3-and-phps-built-in-webserver)

1. navigate a terminal to the 'examples/' folder
2. sqlite3 example.db &lt; example.sql
3. php -S localhost:8080
4. open web browser to

Install from composer
---------------------

[](#install-from-composer)

```
composer require phpbootstraptableedit/phpbootstraptableedit

```

Important Terminology - index, add, edit
----------------------------------------

[](#important-terminology---index-add-edit)

- "index" is the opening table showing all records, pagination, and search
- "add" is the form to insert new records
- "edit" is the form to update existing records

```
$o->index_sql = "";       // sql to define the opening grid
$o->index_sql_param = []; // named params
$o->index = [];           // field settings on index table

$o->add_sql = "";         // sql to define the fields when adding a record
$o->add_sql_param = [];   // named params
$o->add = [];             // field settings on add form

$o->edit_sql = "";        // sql to define the fields when editing a record
$o->edit_sql_param = [];  // named params
$o->edit = [];            // field settings on edit form
```

Caution

Stop SQL injection attacks, never place user input into SQL strings! Instead, use *sql\_param* arrays to safely pass input.

Tip

Use the *nonce* properties to prevent Cross-site Request Forgery attacks (CSRF).

Basic Example
-------------

[](#basic-example)

```
$dbh = new PDO('sqlite:example.db');

$o = new PHPBootstrapTableEdit\PHPBootstrapTableEdit($dbh);

$o->table_name = 'markets';
$o->identity_name = 'id';

// define opening index table, to render the [edit] link, the last column must be the identity id
$o->index_sql = "
select m.title,
       c.title as country,
       m.create_date,
       case when m.is_active = 1 then 'Yes' else '-' end as is_active,
       m.id
from   markets m
left
join   countries c
on     m.country = c.code
where  ( coalesce(m.title, '') like :search or coalesce(c.title, '') like :search )
order by 2 desc
";

// named parameters for search
$o->index_sql_param[':search'] = '%' . trim($_REQUEST['_search'] ?? '') . '%';

// define fields on the edit form
$o->edit_sql = "select title, email, country, create_date, is_active from markets where id = :id";
$o->edit_sql_param[':id'] = intval($_POST['id'] ?? $_GET['id'] ?? 0);

// floating input style
$o->floating = true;

// define fields attributes
$o->edit['title']['required'] = true;
$o->edit['country']['type'] = 'select';
$o->edit['country']['sql'] = 'select code, title from countries'; // define how to populate the select dropdown
$o->edit['create_date']['type'] = 'date';
$o->edit['is_active']['type'] = 'checkbox';

// 12 column layout - colspan = 4 creates a three column layout
$o->edit['title']['colspan'] = '4';
$o->edit['email']['colspan'] = '4';
$o->edit['country']['colspan'] = '4';
$o->edit['is_active']['colspan'] = '4';
$o->edit['create_date']['colspan'] = '4';

// copy all 'edit' setting into 'add', the add form is the same
$o->add = $o->edit;
$o->add_sql = $o->edit_sql;
$o->add_sql_param = $o->edit_sql_param;

// call the controller
$o->run();
```

Properties
----------

[](#properties)

**charset** (string), output charset, default: 'UTF-8'

**table\_name** (string), database table

**identity\_name** (string), the auto increment id field in the table, typically 'id'

**index\_sql** (string), sql query to define the opening html table listing all records

**index\_sql\_param** (array), parameters for index\_sql

Example:

```
$o->index_sql_param = [':_search' => '%' . trim($_GET['search'] ?? '')  . '%'];
```

**add\_sql** (string), sql query to define what fields to display on the add page, also what fields are in the insert

Example:

```
// no record is returned from this query, just meta data; the field names
$o>->add_sql = "select field1, field2, id from table where id = 0";
```

**add\_sql\_param** (array), named parameters for add\_sql, typically not required since no records are retrieved

**edit\_sql** (string), sql query to define what fields to display on the edit page, also what fields are used in the update

Example:

```
$o>->edit_sql = "select field1, field2, id from table where id = :id";
```

**edit\_sql\_param** (array), named parameters for edit\_sql

Example:

```
$o->add_sql_param[':id'] = $_GET['id'] ?? $_POST['id'];
```

**add** (array), define how fields in add\_sql are rendered on the add form

Example:

```
$o->add['country']['type']     = 'select';
$o->add['country']['required'] = true; // normal html prop/attr
$o->add['country']['sql']      = 'select code, title from countries'; // custom html attribute to define options
$o->add['country']['colspan']  = '3'; // layout
```

**edit** (array), define how fields in edit\_sql are rendered on the edit form

Example:

```
$o->edit['country']['type']     = 'select';
$o->edit['country']['required'] = true; // normal html prop/attr
$o->edit['country']['sql']      = 'select code, title from countries'; // custom html attribute to define options
$o->edit['country']['colspan']  = '3'; // layout

// or we could have copied setting from add to edit, or vice versa
// $o->edit['country'] = $o->add['country'];
```

**index** (array), define hooks to render fields on the opening table, function name, or closure

Example:

```
$o->index['create_date']['function'] = function($data) { return date('d/m/Y', strtotime($data['value'])); };
```

**floating** (bool), enable Bootstrap's floating labels on add and edit forms.

**nonce\_name** (string), csrf field name, default 'nonce'

**nonce\_value** (string), csrf field value

**limit** (int), pagination limit records/page, 0 = off, default = 100

**ellipse\_at** (int), truncate text on index table, 0 = off, default = 0

**query\_string\_carry** (array) entries in this array added to all query strings, useful to carry data from page to page

Example:

```
// carry parent_id in the querystring
// now try appending '&parent_id=5' on to the location bar; value will remain after editing, searching, or paging
$o->query_string_carry[] = 'parent_id';
```

**i18n** (array), associative array containing all localization settings

Defaults:

```
$o->i18n['no_records' => 'No Records', 'not_found' => 'Not Found', 'search' => 'Search', 'edit' => 'Edit', 'add' => 'Add', 'add_2' => 'Add', 'back' => 'Back', 'delete' => 'Delete', 'update' => 'Update', 'delete_file' => 'mark for removal', 'update_success' => 'Updated', 'insert_success' => 'Added', 'delete_success' => 'Deleted'];
```

**css** (array), css class settings

Defaults:

```
$o->css['index_table' => 'table-striped table-hover', 'index_active' => 'table-primary', 'pagination' => ''];
```

**redirect** (bool) helpful when debugging, set to false and page will not redirect after insert/update/delete

'on' Event Hooks
----------------

[](#on-event-hooks)

'on' event hook functions are called before the sql insert/update/delete. 'on' functions can be used to cast POST data or add validation. Returning a string from an 'on\_' function displays an alert on the add/edit form and skips the insert/update/delete.

- **on\_insert** (closure or function name)
- **on\_update** (closure or function name)
- **on\_delete** (closure or function name)

Text Only Alert:

```
$o->on_insert = function()
{
   if(strlen($_POST['email'] ?? '') == 0) {
       return "Email Required";
   }
}
```

HTML and Text Alerts:

```
$o->on_update = function()
{
    return ['html' => 'unescaped html, or maybe just passing some json',
            'text' => 'optional, I appear in an alert div on the edit form'];

}
```

'after' Event Hooks
-------------------

[](#after-event-hooks)

after functions are called after the SQL insert/update/delete. after\_insert is a unique hook, it's receives an argument; the inserted id.

- **after\_insert** (closure or function name)
- **after\_update** (closure or function name)
- **after\_delete** (closure or function name)

Examples:

```
$o->after_insert = function($id)
{
    // i'm unique, i have the inserted id as an argument
}

$o->after_update = function()
{
    // all other hooks have to get their own identity key
    $id = $_POST['id'];
}
```

Normal HTML Attributes
======================

[](#normal-html-attributes)

Standard HTML attributes can be set in the *add* and *edit* arrays. They are passed through as expected

```
$o->edit["title"]["type"]      = "text"; // text is already a default, no need to specify text
$o->edit["title"]["maxlength"] = "25";
$o->edit["title"]["foo"]       = "bar";
$o->edit["title"]["required"]  = true; // use true/false for properties

// outputs:
//
```

Custom HTML Attributes
======================

[](#custom-html-attributes)

Custom attributes instruct this library how to render the input. Unlike normal HTML attributes, such as maxlength, custom attributes do not appear in the input.

- **colspan** (string) Bootstrap forms have a 12 column layout, so using '4' on all fields would creates a 3 column layout; 12/4 = 3

Example:

```
$o->edit[field]['colspan'] = "4";
```

- **div\_class** (string) add a class to the div wrapping the input

Example:

```
// in this example 'form-switch' is added to make a checkbox render as a switch
$o->edit[field]['div_class'] = "form-switch";
```

- **label** (string), rename the title appearing with the field

Example:

```
$o->add[field]['label']   = "Country";
$o->edit[field]['label']  = "Country";
$o->index[field]['label'] = "Country";
```

- **sql** (string) sql statement to populate a select, radio, or checkbox input Example:

```
// the first column is the value, the second column is the displayed title
$o->edit[field]['sql'] = "select code, title from countries";
```

- **sql\_param** (array), associative array to hold named parameters for sql

Example:

```
$o->edit[field]['sql_param'] = array(":code" = $_GET['code']);
```

Custom HTML Attributes for File Uploads
=======================================

[](#custom-html-attributes-for-file-uploads)

- **file\_extension** (string) Define what type of file to accept. For images, valid formats are png, gif, jpg, format and meta are verified at upload. For non-images, such as doc or pdf, format and meta are not verified at upload.

Example:

```
$o->edit[field]['file_extension'] = 'png'; // this still allows gif or jpg to be uploaded, but saved binary will be png
```

- **file\_path** (string) Optional, filesystem location for files to be uploaded to; a filename is stored in the database field. If no file\_path is specified, the binary content is stored directly into the database field, and no filename is saved.

Example:

```
// store files here:
$o->edit[field]['file_path'] = '/by/listing/a/path/file/is/saved/to/the/filesystem';

// no path means save binaries in the database field; field must be a blob, no filename is saved
$o->edit[field]['file_path'] = null;
```

- **file\_image\_width** (int) Optional, when file\_extention is png, gif, or jpg, specify a desired width.

Example:

```
$o->edit[field]['file_image_width'] = 100;
```

- **file\_image\_height** (int) Optional, when file\_extention is png, gif, or jpg, specify a desired height.

Example:

```
$o->edit[field]['file_image_height'] = 100;
```

- **file\_image\_crop\_or\_resize** (string, 'crop' or 'resize') optional, specify how to resize the image when file\_extention; for png, gif, or jpg only. 'crop' creates an image accoring to width and height settings. 'resize' maintains aspect ratio of the original image while limiting size to width and height settings. Example:

```
$o->edit[field]['file_image_crop_or_resize'] = 'crop'; // valid options: 'crop' or 'resize'
```

Label - Rename a field
======================

[](#label---rename-a-field)

Rename the title appearing with the field Example:

```
// make country_code appear as Country
$o->add['country_code']['label']   = "Country";
$o->edit['country_code']['label']  = "Country";
$o->index['country_code']['label'] = "Country";
```

###  Health Score

23

—

LowBetter than 26% of packages

Maintenance34

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity32

Early-stage or recently created project

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

Recently: every ~45 days

Total

8

Last Release

625d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/61b348c43d16a98cab60464a21ff6dbea7fda196c7f2dab9d09330acb3e9b813?d=identicon)[pbte](/maintainers/pbte)

---

Top Contributors

[![lazymofo](https://avatars.githubusercontent.com/u/6475096?v=4)](https://github.com/lazymofo "lazymofo (13 commits)")

### Embed Badge

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

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

###  Alternatives

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k117.2M117](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8351.6M87](/packages/propel-propel1)[jfelder/oracledb

Oracle DB driver for Laravel

11518.4k](/packages/jfelder-oracledb)

PHPackages © 2026

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