finesse/mini-db

轻量级数据库抽象,带有查询构建器

v0.7.4 2019-02-15 06:48 UTC

This package is auto-updated.

Last update: 2024-08-29 04:48:25 UTC


README

Latest Stable Version Total Downloads PHP from Packagist Test Status Maintainability Test Coverage

轻量级数据库抽象,行简单为数组。它既有一个查询构建器,用于方便的流畅语法,又有一个执行纯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');

请注意,如果查询的第二或后续语句有错误,statementsimport方法不会抛出异常。这是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 文件