Extends the BootPress Database Component to create and update tables and indexes at will, and simplifies FTS full-text searching.
Extends the BootPress Database Component to easily create and update SQLite database tables and indexes at will. It overrides the underlying PDO wrappers of the Database Component to use the PHP SQLite3 class. The main reason is so that you can free the file from it's cold dead hands when you $db->connection()->close()
. The only side effect of that is you can't fetch 'obj' or 'named' rows. Otherwise, we are just adding more functionality here. It also facilitates FTS full-text searching.
A BootPress\SQLite\Fts instance.
Create an SQLite FTS4 virtual table for fulltext searching.
The database table name.
An array($field, ...)
of names to create, or just a string (eg. 'search') if there is only one field name.
Either 'simple', or 'porter' (the default).
Either false
if the table has already been created, or true
if the table has been created anew.
if ($db->created) {
$db->fts->create('results', 'search');
// You can insert, update, and query an FTS table the same as any other.
if ($stmt = $db->insert('results', array('docid', 'search'))) {
$db->insert($stmt, array(100, 'Fisherman never die, they just get reel tired.'));
$db->insert($stmt, array(101, 'If wishes were fishes, we\'d have a fish fry.'));
$db->insert($stmt, array(102, 'Women want me, fish fear me.'));
$db->insert($stmt, array(103, 'Good things come to those who bait.'));
$db->insert($stmt, array(104, 'A reel expert can tackle anything.'));
}
}
Get the total number of search results.
The database table name.
The search term(s) to 'MATCH'.
An additional string of restrictions you would like to place. If you don't include 'WHERE' we will add it for you. If you are combining tables to deliver results then put your 'INNER JOIN ... WHERE' clause here, and prefix the search $table and fields with 's.' eg. INNER JOIN my_table AS my ON s.docid = my.id WHERE my.field = ...
The total count.
echo $db->fts->count('results', 'fish'); // 2
Queries an FTS $table for the relevant $search word(s) found within.
The database table name.
The search term(s) to 'MATCH'.
If you are not paginating results and only want the top whatever, then this is an integer. Otherwise it is an SQL ' LIMIT offset, length' clause.
An additional string of restrictions you would like to place. If you don't include 'WHERE' we will add it for you. If you are combining tables to deliver results then put your 'INNER JOIN ... WHERE' clause here, and prefix the search $table and fields with 's.' eg. INNER JOIN my_table AS my ON s.docid = my.id WHERE my.field = ...
An array('s.field', ...)
of additional fields you would like to include in the search results. Remember to specify the table prefixes if needed.
An array of importance that you would like to place on the $table fields searched in whatever order you placed them originally. The default weights are 1 for each field, meaning they are all of equal importance. If you want to make one field more relevant than another, then make this an array($weight, ...)
of importance to place on each corresponding $table field. Even if you place an importance of 0 on a field it will still be included among the search results, it will just have a lower rank (possibly 0). All of this assumes you have more than one field in your $table, otherwise this will make no difference whatsoever.
An associative array of results.
var_export($db->fts->search('results', 'fish'));
array(
array(
'docid' => 101,
'snippet' => "If wishes were <b>fishes</b>, we'd have a <b>fish</b> fry.",
'offsets' => '0 0 15 6 0 0 35 4',
'rank' => 1.333,
),
array(
'docid' => 102,
'snippet' => 'Women want me, <b>fish</b> fear me.',
'offsets' => '0 0 15 4',
'rank' => .666,
),
);
Get the words that made your $search relevant for $docid.
The database table name.
The search term(s) to 'MATCH'.
The $table row's docid.
The unique words found which made the $search relevant.
echo implode(', ', $db->fts->words('results', 'fish', 101)); // fishes, fish
Sorts through the $row['offsets'] integers, and retrieves the words they reference.
An associative array of each $fields value, including an 'offsets' key.
An array of field names in the same order as they are found in the database search table.
The words that made this row relevant.
print_r($db->fts->offset(array(
'search' => "If wishes were fishes, we'd have a fish fry.",
'offsets' => '0 0 15 6 0 0 35 4',
), array('search'))); // array('fishes', 'fish');
Whether or not this is a new database.
Connects to an SQLite database $file, and creates one if it doesn't already exist.
The SQLite database file location, or just leave it null
to create an SQLite database in ':memory:'.
Either create an SQLite $table if it has not already been created, or verify that it matches the sqlite_master table index. If something has changed, then the $table will be altered accordingly.
The database table name.
An array($name => $type, ...)
of fields that define this $table.
A string of comma-separated 'field, name, ...'s to index. If you are creating multiple indexes, then make this an array('field', 'name', ... )
of all the indexes you would like to create. If it is a unique index, then make it an array('unique' => 'field, name, ...')
.
When changing field names, make an array($old => $new, ...)
to map the old field name with the new field name, so that all of the data is updated accordingly. You can change the $fields order and type no problem, but if you change field names and don't map them, we'll send the old (missing) field name to the scrapheap, and every new field name will receive it's default value.
Either false
if nothing has changed and the $table is exactly as you would like it, or true
if the $table has been newly created or updated in any way.
if ($db->created) {
$db->create('employees', array(
'id' => 'INTEGER PRIMARY KEY',
'name' => 'TEXT COLLATE NOCASE',
'position' => 'TEXT NOT NULL DEFAULT ""',
), array('unique'=>'position'));
// Wait, I just changed my mind
$db->create('employees', array(
'id' => 'INTEGER PRIMARY KEY',
'name' => 'TEXT UNIQUE COLLATE NOCASE',
'title' => 'TEXT DEFAULT ""',
), 'title', array(
'position' => 'title',
));
}
Create and retrieve database settings.
What you want to either set or return.
The setting's value. If you want to remove the setting, then set this explicitly to null
.
An array of all the settings (if no parameters are given), or the setting's value (if no value is given).
$db->settings('version', '1.2');
echo $db->settings('version'); // 1.2
Returns the $field . 'IN(' . implode(',', $ids) . ')'
, in the same order given. This method is patterned after using MySQL's FIELD() function, which unfortunately is unavailable in SQLite.
Database column.
Those passed to the IN() clause.
An SQL string to put at the end of your query.
if ($ids = $db->ids('SELECT id FROM employees ORDER BY name ASC')) {
foreach ($db->all(array(
'SELECT name, title FROM employees',
'WHERE '.$db->inOrder('id', $ids),
)) as $row) {
list($name, $title) = $row;
}
}
When you overwhelm an SQLite database with overlapping inserts and updates, there's a chance it may become corrupted. If it does, I've been able to recreate it using this method.
The NEW SQLite database file location. The one you want to create.
Add the following to your composer.json
file.
{
"require": {
"bootpress/sqlite": "^1.0"
}
}
<?php
use BootPress\SQLite\Component as Sqlite;
$db = new Sqlite; // An in-memory database
if ($db->created) {
$db->settings('version', '1.0');
$db->create('employees', array(
'id' => 'INTEGER PRIMARY KEY',
'name' => 'TEXT COLLATE NOCASE',
'position' => 'TEXT NOT NULL DEFAULT ""',
), array('unique'=>'position'));
// Wait, I just changed my mind:
$db->create('employees', array(
'id' => 'INTEGER PRIMARY KEY',
'name' => 'TEXT UNIQUE COLLATE NOCASE',
'title' => 'TEXT DEFAULT ""',
), 'title', array(
'position' => 'title',
));
$db->fts->create('results', 'search');
// You can insert, update, and query an FTS table the same as any other.
if ($stmt = $db->insert('results', array('docid', 'search'))) {
$db->insert($stmt, array(100, 'Fisherman never die, they just get reel tired.'));
$db->insert($stmt, array(101, 'If wishes were fishes, we\'d have a fish fry.'));
$db->insert($stmt, array(102, 'Women want me, fish fear me.'));
$db->insert($stmt, array(103, 'Good things come to those who bait.'));
$db->insert($stmt, array(104, 'A reel expert can tackle anything.'));
}
}
echo $db->settings('version'); // 1.0
echo $db->fts->count('results', 'fish')); // 2
print_r($db->fts->search('results', 'fish'));
/*
array(
array(
'docid' => 101,
'snippet' => "If wishes were <b>fishes</b>, we'd have a <b>fish</b> fry.",
'offsets' => '0 0 15 6 0 0 35 4',
'rank' => 1.333,
),
array(
'docid' => 102,
'snippet' => 'Women want me, <b>fish</b> fear me.',
'offsets' => '0 0 15 4',
'rank' => .666,
),
)
*/
echo implode(', ', $db->fts->words('results', 'fish', 101)); // fishes, fish