MENU
.net Powerful JavaScript charts

The SQLite Editor for PHP administration tool

The SQLite Editor for PHP is an administration tool for managing your SQLite databases that you can use to give your users the ability to view, edit and update your database without the danger of them destroying your data.

Introduction

The SQLite Editor for PHP is an administration tool for making interfaces to your SQLite database tables. It's not a full database administration tool however. You cannot use it to add, modify or delete tables, views etc. You wouldn't give such a tool to your users, allowing them to destroy your database! It's a tool that allows the addition, editing and deletion of data in existing tables. Adding, editing and deletion can all be enabled or disabled so you can turn them all off and just allow viewing the data if you wish.

It can be easily integrated into your pages - as you can see from the example below. It's just a single library file which makes it simple to setup and go.

Example

  help
Displaying 1 - 10 of 20
1  2  
ID
Username
Created
Forename
Surname
1519
dunawayf
2026-06-13 12:45:19
ddsad
Dunaway
1522
damonm
2026-06-13 12:45:19
Matt
Damon
1523
blackj
2026-06-13 12:45:19
Jack
black
1525
doudb
2026-06-13 12:45:19
Ben
Doud
1526
sinners
2026-06-13 12:45:19
Steven
Sinner
1528
cosb
2026-06-13 12:45:19
pppp
Cos
1529
jasond
2026-06-13 12:45:19
Jason
Dunny
1530
lindbergc
2026-06-13 12:45:19
Charles
Lindberg
1531
englaisesh
2026-06-13 12:45:19
Hoolio
Englaises
1532
myersm
2026-06-13 12:45:19
Michael
Myers
 (add/edit/delete are disabled on this demo)

And here's the source-code that produces the editor above.

<?php
    require('SQLiteEditor.php');

    $editor = new SQLiteEditor([
        'filename'     => 'examples/sqliteeditor.db',
        'table'        => 'accounts',
        'sql_select'   => "SELECT id,
                                  username,
                                  created,
                                  forename,
                                  surname
                             FROM accounts
                            WHERE {where}
                                  {order}",
        'sql_add' => false,
        'sql_delete' => false,
        'paging_perpage' => 10,
        'columns_names' => [
            'id'       => 'ID',
            'username' => 'Username',
            'created'  => 'Created',
            'forename' => 'Forename',
            'surname'  => 'Surname'
        ],
        'search_columns' => ['forename','surname'],
        'style' => [
            '.sqliteeditor table tbody tr:hover {background-color: #eee;}'
        ],
        'actions' => [
            '<small><i>(add/edit/delete are disabled on this demo)</i></small>'
        ]
    ]);
    
    $editor->draw();
?>

Download

This is the latest zip file download that contains the PHP file (it's just a single file) and the example pages. Extract this zip file to a directory on to your (PHP enabled) web server and all of the examples should run without any further modification or configuration.

Download the SQLite Editor for PHP zip file

Option reference

General properties

Name: filename
Description: 
The filename and path to your database file. This must be given. It can either be a relative path or and absolute path. Examples:
$editor = new SqliteEditor([
    "filename" => "./my.db",
    "table"    => "accounts"
]);

// Possible variations of the path:
// /usr/local/home/web/my.db
// ./my.db
// ../web/my.db
// my.db
Default: null
Name: table
Description: 
The name of the table that you want the editor to be for. This must be given.
Default: null
Name: primary_key
Description: 
This doesn't have to be provided - the editor will try and get this from the description of the table. If your table has no primary key then editing and deleting won't work correctly (if at all).
Default: null

SQL properties

Name: sql_select
Description: 
This is the SQL query that's used to fetch the data to be displayed. You can use any SELECT query that you want but if you use dynamic columns (ie a column in your result set that's actually the result of a function), or if you use a join to fetch columns from another table, those columns will not be editable. If you want to use editing or you want to allow the deletion of rows then you should include the primary key of the table in this query.
Default: SELECT * FROM {table} WHERE {where} {order}
Name: sql_add
Description: 
This is the SQL query that you want to use to add a new row into the table. You can modify the default query and have it add default values for new rows if you want to.

set this option to false to disable the addition of new rows.

This option can also be a function if you want to run some code when a new row is added (or if you want to run multiple SQL queries). The callback function is passed the editor object as its sole argument.

'sql_add' => function ($editor)
{
   // Add your logic here
}
Default: INSERT INTO {table} ({primary_key}) values(null)
Name: sql_update
Description: 
This is the query that's used to update a row after an edit. If you disable editing you can ignore this property (editing rows is disabled by default). The placeholder values in the UPDATE query (shown below) are replaced with the relevant values.

This option can also be a function if you want to run some code when a row is updated (or if you want to run multiple SQL queries). The callback function is passed a number of arguments:

  • The editor object
  • The name of the table
  • The name of the field that was edited
  • The new value
  • The primary key value of the row
  • The name of the primary key column
Default: UPDATE {table} SET {column} = {value} WHERE {primary_key} = {id} LIMIT 1
Name: sql_delete
Description: 
This is the query that's used to delete a row. The default query for this option deletes the row(s) entirely however you could change this so that it updates a deleted column with the current date/time , for example:
UPDATE {table} SET deleted = DATETIME() WHERE {primary_key} IN({ids}))
and then, using the sql_select option, only show rows that have a null deleted column.

Set this option to false in order to disable the deletion of rows.

This option can also be a function if you want to run some code when a row is deleted (or if you want to run multiple SQL queries). The callback function is passed the editor object and an array of ids that were selected for deletion.

'sql_delete' => function ($editor, $ids)
{
   // Add your logic here
}
Default: DELETE FROM {table} WHERE {primary_key} IN({ids}) LIMIT {count}

Editing properties

Name: editable
Description: 
This should be an array of column names that you want to be editable. When a column is editable you can double-click on an entry to edit it. Press [Enter] when you've finished and the new value will be sent back to the page using an AJAX POST request, where it will be saved back to the database using the SQL query that's specified in the sql_update option. Note that if the column is dynamic (for example, it's the result of an SQL function call) then when it comes to saving the value it will fail.
Default: false
Name: editable_callback_url
Description: 
If you wish, you can have the AJAX call for edits request a different URL than itself when saving a value. The following POST data is passed to the URL:
{
  sqliteeditor_action: "save",// Always set to "save"
sqliteeditor_database: ...,   // The database filename
   sqliteeditor_table: ...,   // The table in question
  sqliteeditor_column: ...,   // The column name being edited
   sqliteeditor_value: ...    // The new value
   sqliteeditor_index: ...,   // The value of the primary key
 sqliteeditor_primary: ...    // The name of the primary key field
   
}
Default: null
Name: editable_log_response
Description: 
If you set this to true then the output of the POST request, that is made when you edit a value, is logged to the browsers JavaScript console. This allows you to debug your script that saves the edited value.
Default: false

Columns properties

Name: columns_names
Description: 
Friendly names for the columns instead of the database column name which are used when showing the editor.
Default: [an empty array]
Name: columns_widths
Description: 
This can be an associative array of specific column widths that you want to be applied to the resulting table. For example, you might be showing the ID column of your table but want it to have a smaller width than the default value. You could do this:
'columns_widths' => [
    'id' => 50
]
Default:  [an empty array]
Name: columns_tooltips
Description: 
This can be an associative array of true or false values controlling whether a tooltip is applied to the values in the column. It could look like this:
'columns_tooltips' => [
    'id'       => false,
    'forename' => true,
    'forename' => true
]
Default: null
Name: columns_callbacks
Description: 
This option allows you to specify PHP functions (one per column) that are called when the values in that column are being displayed. For example, if you're showing a DATETIME column, which is in the format YY-MM-DD HH:MM:SS, but want to show it in a more human-readable form, for example, 21st July 2007, then you can use this option to do that if you want. If you prefer, you could also format the column in your SQL query, using the SQLite formatting functions, and you might not not need to use this option. For example:
'columns_callbacks' => [
    'created' => function ($obj, $row_data, $name, $value)
    {
        if ($value) {
            return date('jS F Y', strtotime($value));
        }
    }
]
You could also use the callback function to create "action" buttons at the end of each row, for example:
'columns_callbacks' => [
    'actions' => function ($obj, $row_data, $name, $value)
    {
        return '<button onclick="location.href=\'account.html?id=' . $row_data['id'] . '\'">View account details</button>';
    }
]

The callback function is passed the following arguments:

  • The editor object.
  • An array of the whole row that is currently being processed.
  • The column name.
  • The value of the cell
Default:  [an empty array]
Name: columns_escape
Description: 
By default, all the column values and column names are escaped so that any HTML in the text will be seen as-is. If this is not desirable and you want to see the effect of any HTML tags (eg <b>, <i> or even <img>) you can set the relevant column name to false in this array. For example:
'columns_escape' => [
    'forename' => false,
    'surname'  => false
]
Default: [an empty array]

Paging properties

Name: paging_current
Description: 
This setting allows you to set the page that's being displayed. It's important to remember though that this is overridden by the paging_[id] GET parameter. This allows you to set the initial page that is displayed to the user but they can then navigate to other pages using the paging links.
Default: 1
Name: paging_perpage
Description: 
If you want to see a different amount of results on the page than the default you can use this setting to set the number of results to show.
Default: 25

Search properties

Name: search
Description: 
This setting allows you to enable or disable the search function. The search allows you to enter one or more keywords, hit enter on your keyword and the results will be limited to rows that contain that text. If you enter multiple keywords the results will be those that contain both keywords - an AND search.
Default: true
Name: search_columns
Description: 
This allows you to restrict the search to one or more columns. It should be an array that contains the column names that you want to allow to be searched. For example:
<?php
    require("SQLiteEditor.php");

    $editor = new SQLiteEditor([
        "filename"     => "examples/sqliteeditor.db",
        "table"        => "accounts",
        "search_columns" => ["forename","surname"]
    ]);

    $editor->draw();
?>
Default: null

Ordering properties

Name: ordering_column
Description: 
The column that you want to order by. Instead of specifying the ordering in your SQL query you can set it here. If not given, then no ordering will be applied by default.
Default: null
Name: ordering_dir
Description: 
The direction that you want to sort by - either asc or desc. If not given, there will be no direction specified but the user will be able to change it by clicking on the column headers.
Default: null
Name: ordering_exclude
Description: 
If you want to exclude certain columns from being able to be ordered, you can specify the names of those columns with this property.
Default: [an empty array]
Name: ordering_changeable
Description: 
By default, this is true and makes it so that the user can change the ordering as they wish by clicking on the column headers. If you set this to false then the user will not be able to change the ordering.
Default: true

Miscellaneous properties

Name: styles
Description: 
This can be an array of strings which contain style declarations that are added to the document. You can apply styles to the editor and you can even set styles for other elements on the page. The <style> block that's added to the document is added at the end of the <head> section of the page. For example:
'styles' => [
    '.sqliteeditor_button_delete {font-size: 16pt;}',
    '.sqliteeditor_button_add {font-size: 16pt;}',
    '.sqliteeditor button {font-size: 16pt;}',
    '.sqliteeditor input[type=checkbox] {transform: scale(1.5); cursor: pointer;}',
    '.sqliteeditor table tbody tr :where(th, td)[data-column-name=id] {text-align: center;}',
    '.sqliteeditor table tbody tr:hover :not(td.checkbox_table_cell) {background-color: #eee;}'
]
Default: [an empty array]
Name: actions
Description: 
You can use this property to add extra buttons below the editor table, where the add and delete buttons are. There are two ways to use this roperty - the first is to supply an array of the label of the button and some JavaScript that is run when the button is pressed. In this case event.preventDefault(); is added after your JavaScript so that the page doesnt refresh. This option looks like this:
'actions' => [
    ['Hello world!', "alert('Hello world!');"],
]
The other option is just to give a string in the actions array instead of the two element array. In this case the string is simply printed as-is so you can control every aspect of the button. This option looks like this:
'actions' => [
    '<button onclick=" alert('Hello world!'); event.preventDefault()">Hello world!</button>'
]

When writing your JavaScript to go here (for example in the onclick event listener) there's a macro that you can use: {id} which is replaced by the id of the editor (wrapped in quotes). This is intended for use with the sqlite_getchecked function but you can use it for other reasons if you so wish. You'd use it like this:

'actions' => [
    ['Hello world!', 'var checked = sqliteeditor_getchecked({id}); alert(checked);'],
    '<button onclick="event.preventDefault(); var checked = sqliteeditor_getchecked({id}); alert(checked);">Hello world!</button>'
]

Using this option, you don't necessarily have to add a button - it could be any snippet of HTML that you want to add to the page. So you could, for example, add an image, a set of images or a select element (useful for when you have lots of actions that you want to give to the user) or your own menu system that provides multiple options to the user.
Default: [an empty array]
Name: checkboxes
Description: 
If you've disabled the deletion of rows by setting the sql_delete option to false the checkboxes on the left side of the rows will not be shown. You might, however, want the checkboxes for your own purposes. For example, you might have an action button that uses the sqliteeditor_getchecked() function. So by setting this option to true you can reenable the checkboxes.
Default: false

Methods

These are JavaScript functions that you can call from within the page should you need to.

Name: void sqliteeditor_setpage(string id, number page)
Description: 
Call this function to set the page number that's currently being displayed.
Name: array sqliteeditor_getchecked([string id = null])
Description: 
This method returns an array of the values of the checkboxes that are added to the start of each row which are checked. These values are typically the primary key values of the rows in the database. If your table doesn't have a primary key though - this method will not function correctly.

If you only have a single editor on the page then you don't need to provide an argument. If you do have multiple editors on the page though you will need to provide the id (eg sqle1) of the editor that you want to query.

When you use this with the actions option (detailed above) there's a macro that you can use to make things easier - just add {id} (no quotes - it's not a string) instead of the id argument to the function and the editor will replace it with the correct id. Like this:

'actions' => [
    ['Hello world!', 'var checked = sqliteeditor_getchecked({id}); alert(checked)'],
    '<button onclick="event.preventDefault();var checked = sqliteeditor_getchecked({id}); alert(checked)">Hello world!</button>'
]

Search functionality

The search functionality was originally based on a LIKE condition added to the SELECT query which translated to a simple wildcard search - finding whatever you typed in if it was part of the row.

From version 1.0b3, however, the search has been converted to a GLOB clause which results in a few extra options that are available to you when searching.

There are two wildcard characters available to you and they are:

Asterisks are added to both ends of the term(s) that you search for. So a search for cde would find the word abcdefgh. Also, you can add a ! to the start of a word or sequence of characters to negate it.

So a search for the phrase john !Barry would find rows that contain the word john but not with the word barry.

Character classes

Similar to regular expressions you can use square brackets - [] - to define a range of characters. So the following: [abcdef] would match any of those characters - but only one of them. And you can also negate the character class by adding a caret sign at the start like this: [^abcdef] Remember though that this type of character class only matches a single character and if you negate the class it will match any character that's not in that class.

Negating a whole word

If you want to negate a whole word (so maybe you could search for: big yellow !balloons, which would look for rows that contain the words big and yellow but not the word balloons, then you can prefix an exclamation point to that word.

Examples

blackSearch for rows that contain the word black
!blackSearch for rows that DO NOT contain the word black
jack blackSearch for rows that contain both of the words jack and black
jack !blackSearch for rows that contain the word jack but DO NOT contain the word black
ja[chdrt]kSearch for rows that contain the given word where the third character can be c,h,d,r or t
ja[^chdrt]kSearch for rows that contain the given word where the third character MUST NOT be c,h,d,r or t

License

The SQLiteEditor tool has the same license as SQLite itself - ie it is released to the public domain and you can do with it as you wish.

FAQs

What's the license of the software?

The SQLite Editor for PHP software is released to the public domain without any conditions. This means that you can use it freely, as much as or as little as you want to, royalty-free.

Does this software support any other types of database?

No, but the SQLite-specific parts of the code are minimal so converting it to or adding support for another type of database won't be difficult.

Is it possible not to delete rows and, instead, mark them as deleted?

Yes, you can do that by changing the default queries. You would change the sql_delete query to update a "deleted" flag on the row instead of performing a delete query and also change the default sql_select option to one that excludes rows that have that deleted flag set (the default for that column should be null).

Can I add one or more buttons to the right of each row?

Yes, you can do this by selecting an empty column in your query and then using the columns_callbacks option to set the HTML for that column. The sql_select option query that selects data for the editor would look like this (the columns_escape option is also set here for this column so the HTML appears instead of the HTML code itself):

'sql_select'   => "SELECT id,
                          username,
                          created,
                          forename,
                          surname,
                          '' AS `actions`
                     FROM accounts",
'columns_escape' => ['actions' => false],

You could add a columns_names property like this so that the new column does not have a heading. You'd need to use CSS if your headings have a background color but you don't want one for this column.

'columns_names' => [
    'id'       => 'ID',
    'username' => 'Username',
    'created'  => 'Created',
    'forename' => 'Forename',
    'surname'  => 'Surname',
    'actions'  => ''
],

And then in the columns_callbacks option you would need to add the code the creates the button that's added to that empty column.

'columns_callbacks' => [
    'actions' => function ($obj, $row_data, $name, $value)
    {
        return sprintf('<button onclick="event.preventDefault(); location.href = \'account.php?id=%d\'">View account</button>', $row_data['id']);
        
        // This creates a dropdown list instead of a button. It
        // might be more useful to you if you have a lot of actions.
        // return sprintf('<select onchange="location.href = this.value"><option></option><option value="account.php?id=' . $row_data['id'] . '">View account</option></select>');
    }
],

There's an example in the download archive called examples/accounts.php that demonstrates this technique.

Changelog

The search has been updated to use the SQLite GLOB functionality instead of the LIKE functionality. This makes it a bit more versatile for you so you can search for data in a few more ways. You can read about the ways that you can search in the search section above.

You can now sort the data by clicking the column headers. You can click the header multiple times to cycle through ascending, descending and not sorted. If you use the callbacks to alter the output then the resulting sorting may be unpredictable.

There was some mixing of the styles property where it was called style (no 's') in some places. This has been rectified and the correct term, styles, is what you should use.

A search was added that enables you to search within the results. Internally, a LIKE query is performed doing this style of match %word1% AND %word2% AND %word3% etc. The search-clause is added to your select query when the user performs a search.

This was the initial release of the SQLite Editor for PHP software. Read through the documentation - specifically the API documentation - to learn about the features that are available to you.