finesse / mini-db
轻量级数据库抽象,带有查询构建器
Requires
- php: >=7.0
- finesse/micro-db: ^0.2.2
- finesse/query-scribe: ^0.9.3
Requires (Dev)
- ext-pdo_sqlite: *
- pagerfanta/pagerfanta: ^1.0 || ^2.0
- phpunit/phpunit: ^6.4
Suggests
- pagerfanta/pagerfanta: To make pagination
README
轻量级数据库抽象,行简单为数组。它既有一个查询构建器,用于方便的流畅语法,又有一个执行纯SQL查询的接口。
$database = Database::create([ 'driver' => 'mysql', 'dsn' => 'mysql:host=localhost;dbname=my_database', 'username' => 'root', 'password' => 'qwerty', 'prefix' => 'test_' ]); $database->statement(' CREATE TABLE '.$database->addTablePrefix('users').' ( id INT(11) NOT NULL AUTO_INCREMENT, email VARCHAR(50) NOT NULL, account INT(11) NOT NULL DEFAULT 0 ) '); $database->table('users')->insert([ ['name' => 'Jack', 'account' => 1200], ['name' => 'Bob', 'account' => 500], ['name' => 'Richard', 'account' => 800] ]); $database->table('users')->where('account', '>', 600)->get(); // Jack and Richard
关键特性
- 轻量级,依赖项数量少。
- 可扩展。示例即将到来。
- 查询构建器和数据库连接器可以单独使用。
- 支持表前缀。
- 无静态外观。使用依赖注入显式交付。
- 错误时抛出异常。
支持的数据库管理系统
- MySQL
- SQLite
- 也许还有其他,尚未测试
如果您需要支持新的数据库系统,请在此和此处使用pull requests实现。
安装
您需要Composer来使用此库。在控制台中运行
composer require finesse/mini-db
参考
入门
您需要创建一次Database
实例
use Finesse\MiniDB\Database; $database = Database::create([ 'driver' => 'mysql', // DBMS type: 'mysql', 'sqlite' or anything else for other (optional) 'dsn' => 'mysql:host=host;dbname=db', // PDO data source name (DSN) 'username' => 'root', // Database username (optional) 'password' => 'qwerty', // Database password (optional) 'options' => [], // PDO options (optional) 'prefix' => '' // Tables prefix (optional) ]);
有关PDO选项的更多信息,请参阅PDO构造函数参考。
或者,您可以手动创建所有依赖项
use Finesse\MicroDB\Connection; use Finesse\MiniDB\Database; use Finesse\QueryScribe\Grammars\MySQLGrammar; use Finesse\QueryScribe\PostProcessors\TablePrefixer; $connection = Connection::create('mysql:host=host;dbname=db', 'username', 'password'); $grammar = new MySQLGrammar(); $tablePrefixer = new TablePrefixer('demo_'); $database = new Database($connection, $grammar, $tablePrefixer);
原始SQL查询
$database->insertGetId('INSERT INTO users (name, email) VALUES (?, ?), (?, ?)', ['Ann', 'ann@gmail.com', 'Bob', 'bob@rambler.com']); // 19 (the last inserted row id) $database->select('SELECT * FROM users WHERE name = ? OR email = ?', ['Jack', 'jack@example.com']); /* [ ['id' => 4, 'name' => 'Jack', 'email' => 'demon@mail.com', 'account' => 1230], ['id' => 17, 'name' => 'Bill', 'email' => 'jack@example.com', 'account' => -100] ] */ $database->import('path/to/file.sql');
单元格值以与底层数据库连接相同的方式返回。它们不会被自动转换,因为转换可能会造成数据丢失。
原始查询不应用表前缀。使用$database->addTablePrefix()
应用它。
$database->select('SELECT * FROM '.$database->addTablePrefix('users').' ORDER BY id');
请注意,如果查询的第二或后续语句有错误,statements
和import
方法不会抛出异常。这是PDO的一个bug。
有关原始查询的更多信息,请参阅此处。
查询构建器
这里展示了基本示例。您可以在此处找到更多酷炫示例。
传递给查询构建器的值被安全处理,以防止SQL注入,因此您不需要对它们进行转义。
选择
多行
$database ->table('users') ->where('status', 'active') ->orderBy('name') ->offset(40) ->limit(10) ->get(); /* [ ['id' => 17, 'name' => 'Bill', 'email' => 'jack@example.com', 'status' => 'active'], ['id' => 4, 'name' => 'Jack', 'email' => 'demon@mail.com', 'status' => 'active'] ] */
一行
$database ->table('users') ->where('status', 'active') ->orderBy('name') ->first(); /* ['id' => 17, 'name' => 'Bill', 'email' => 'jack@example.com', 'status' => 'active'] or null */
分页
我们建议使用Pagerfanta轻松进行分页。
首先,使用composer通过在控制台中运行来安装Pagerfanta
composer require pagerfanta/pagerfanta
然后创建一个查询,从中提取行
$query = $database ->table('posts') ->where('category', 'archive') ->orderBy('date', 'desc'); // Don't call ->get() here
然后使用Pagerfanta
use Finesse\MiniDB\ThirdParty\PagerfantaAdapter; use Pagerfanta\Pagerfanta; $paginator = new Pagerfanta(new PagerfantaAdapter($query)); $paginator->setMaxPerPage(10); // The number of rows on a page $paginator->setCurrentPage(3); // The current page number $currentPageRows = $paginator->getCurrentPageResults(); // The rows for the current page $pagesCount = $paginator->getNbPages(); // Total pages count $haveToPaginate = $paginator->haveToPaginate(); // Whether the number of results is higher than the max per page
您可以在此处找到更多关于Pagerfanta的参考和示例。
行分块
如果您需要处理大量行,可以使用分块。在这种方法中,部分行从数据库中检索,而不是一次性检索所有行。
$database ->table('users') ->orderBy('id') ->chunk(100, function ($users) { foreach ($users as $user) { // Process a row here } });
聚合
$database ->table('products') ->where('price', '>', 1000) ->count(); // 31
其他聚合方法:avg(column)
,sum(column)
,min(column)
和max(column)
。
插入
多行
$database->table('debts')->insert([ ['name' => 'Sparrow', 'amount' => 13000, 'message' => 'Sneaky guy'], ['name' => 'Barbos', 'amount' => 4999, 'message' => null], ['name' => 'Pillower', 'message' => 'Call tomorrow'] ]); // 3 (number of inserted rows)
字符串数组的键是列名。
一行
$database->table('debts')->insertGetId([ 'name' => 'Bigbigger', 'amount' => -3500, 'message' => 'I owe him' ]); // 4 (id of the inserted row)
从选择查询
$database->table('debts')->insertFromSelect(['name', 'amount', 'message'], function ($query) { $query ->from('users') ->addSelect(['name', $query->raw('- account'), 'description']) ->where('status', 'debtor'); }); // 6 (number of inserted rows)
更新
$database ->table('posts') ->where('date', '<', '2017-01-01') ->update([ 'status' => 'obsolete', 'category' => null ]); // 5 (number of updated rows)
数组键是列名。
删除
$database ->table('messages') ->where('sender_id', 1456) ->orWhere('status', 'stink') ->delete(); // 5 (number of deleted rows)
辅助工具
转义 LIKE 特殊通配符字符
$searchString = '%iamhacker%'; $query->where('name', 'like', $query->escapeLikeWildcards($searchString).'_'); // "name" LIKE \%iamhacker\%_
将表名或列名用引号括起来
$query->whereRaw('MIN('.$query->quoteIdentifier('data"base').'.'.$query->quoteIdentifier('ta"ble').') > 10'); // or $query->whereRaw('MIN('.$query->quoteCompositeIdentifier('data"base.ta"ble').') > 10'); // MIN("data""base"."ta""ble") > 10
上述方法也适用于 Database
对象。
使查询中的所有列名都有显式的表名或别名
$database ->table('users', 'u') ->addSelect('name') ->where('status', 'verified') ->orWhere('u.type', 'admin') ->addTablesToColumnNames(); // SELECT "name" FROM "users" AS "u" WHERE "status" = ? OR "u"."type" = ?
版本兼容性
该项目遵循 语义化版本控制。
许可
MIT 许可。有关详细信息,请参阅 LICENSE 文件。