fulfillment/picodb

极简数据库查询构建器

1.0.0 2018-07-31 01:54 UTC

This package is auto-updated.

Last update: 2024-09-09 23:17:21 UTC


README

PicoDb 是一款针对 PHP 的极简数据库查询构建器。

特点

  • 易于使用,易于修改,快速且非常轻量级
  • 支持的驱动器:Sqlite、Mssql、Mysql、Postgresql
  • 仅需要 PDO
  • 使用预编译语句
  • 处理模式迁移
  • 完全在 PHP 5.3、5.4、5.5、5.6 和 7.0 上进行单元测试
  • 许可证:MIT

要求

  • PHP >= 5.3
  • PDO 扩展
  • Sqlite、Mssql、Mysql 或 Postgresql

作者

Frédéric Guillot

文档

安装

composer require elvanto/picodb

数据库连接

Sqlite

use PicoDb\Database;

// Sqlite driver
$db = new Database(['driver' => 'sqlite', 'filename' => ':memory:']);

默认情况下,Sqlite 驱动程序启用外键。

Microsoft SQL服务器

// Optional attributes:
// "schema_table" (the default table name is "schema_version")

$db = new Database([
    'driver' => 'mssql',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'my_db_name',
]);

可选属性

  • schema_table

Mysql

$db = new Database([
    'driver' => 'mysql',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'my_db_name',
    'ssl_key' => '/path/to/client-key.pem',
    'ssl_cert' => '/path/to/client-cert.pem',
    'ssl_ca' => '/path/to/ca-cert.pem',
]);

可选属性

  • charset
  • schema_table
  • port
  • ssl_key
  • ssl_cert
  • ssl_key
  • persistent
  • timeout
  • verify_server_cert
  • case

Postgres

$db = new Database([
    'driver' => 'postgres',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'my_db_name',
]);

可选属性

  • port
  • schema_table

从环境变量连接

假设你已定义了一个环境变量

export DATABASE_URL=postgres://user:pass@hostname:6212/db

PicoDb 可以自动解析此 URL

use PicoDb\UrlParser;
use PicoDb\Database;

$db = new Database(UrlParser::getInstance()->getSettings());

从 URL 连接

use PicoDb\UrlParser;
use PicoDb\Database;

$db = new Database(UrlParser::getInstance()->getSettings('postgres://user:pass@hostname:6212/db'));

执行任何 SQL 查询

$db->execute('CREATE TABLE mytable (column1 TEXT)');
  • 如果成功,返回 PDOStatement
  • 如果有重复键错误,返回 false
  • 对于其他错误抛出 SQLException

插入

$db->table('mytable')->save(['column1' => 'test']);

$db->table('mytable')->insert(['column1' => 'test']);

获取最后插入的 ID

$db->getLastId();

事务

$db->transaction(function ($db) {
    $db->table('mytable')->save(['column1' => 'foo']);
    $db->table('mytable')->save(['column1' => 'bar']);
});
  • 如果回调返回 null,则返回 true
  • 否则返回回调返回值
  • 如果出现问题,则抛出 SQLException

$db->startTransaction();
// Do something...
$db->closeTransaction();

// Rollback
$db->cancelTransaction();

获取所有数据

$records = $db->table('mytable')->findAll();

foreach ($records as $record) {
    var_dump($record['column1']);
}

更新

$db->table('mytable')->eq('id', 1)->save(['column1' => 'hey']);

$db->table('mytable')->eq('id', 1)->update(['column1' => 'hey']);

删除记录

$db->table('mytable')->lt('column1', 10)->remove();

排序

$db->table('mytable')->asc('column1')->findAll();

$db->table('mytable')->desc('column1')->findAll();

$db->table('mytable')->orderBy('column1', 'ASC')->findAll();

多级排序

$db->table('mytable')->asc('column1')->desc('column2')->findAll();

限制和偏移量

$db->table('mytable')->limit(10)->offset(5)->findAll();

仅获取一些列

$db->table('mytable')->columns('column1', 'column2')->findAll();

仅获取一列

多行

$db->table('mytable')->findAllByColumn('column1');

一行

$db->table('mytable')->findOneColumn('column1');

自定义选择

$db->table('mytable')->select(1)->eq('id', 42)->findOne();

唯一

$db->table('mytable')->distinct('columnA')->findOne();

分组

$db->table('mytable')->groupBy('columnA')->findAll();

计数

$db->table('mytable')->count();

求和

$db->table('mytable')->sum('columnB');

在更新期间求和列值

将值 42 添加到列 "mycolumn" 的现有值中

$db->table('mytable')->sumColumn('mycolumn', 42)->update();

增加列

在单个查询中增加列值

$db->table('mytable')->eq('another_column', 42)->increment('my_column', 2);

减少列

在单个查询中减少列值

$db->table('mytable')->eq('another_column', 42)->decrement('my_column', 1);

存在

如果记录存在,则返回 true,否则返回 false。

$db->table('mytable')->eq('column1', 12)->exists();

左连接

// SELECT * FROM mytable LEFT JOIN my_other_table AS t1 ON t1.id=mytable.foreign_key
$db->table('mytable')->left('my_other_table', 't1', 'id', 'mytable', 'foreign_key')->findAll();

// SELECT * FROM mytable LEFT JOIN my_other_table ON my_other_table.id=mytable.foreign_key
$db->table('mytable')->join('my_other_table', 'id', 'foreign_key')->findAll();

等于条件

$db->table('mytable')
   ->eq('column1', 'hey')
   ->findAll();

IN 条件

$db->table('mytable')
       ->in('column1', ['hey', 'bla'])
       ->findAll();

IN 条件与子查询

$subquery = $db->table('another_table')->columns('column2')->eq('column3', 'value3');

$db->table('mytable')
       ->columns('column_5')
       ->inSubquery('column1', $subquery)
       ->findAll();

LIKE 条件

区分大小写(仅限 Mysql 和 Postgres)

$db->table('mytable')
   ->like('column1', '%Foo%')
   ->findAll();

不区分大小写

$db->table('mytable')
   ->ilike('column1', '%foo%')
   ->findAll();

小于条件

$db->table('mytable')
   ->lt('column1', 2)
   ->findAll();

小于等于条件

$db->table('mytable')
   ->lte('column1', 2)
   ->findAll();

大于条件

$db->table('mytable')
   ->gt('column1', 3)
   ->findAll();

大于等于条件

$db->table('mytable')
    ->gte('column1', 3)
    ->findAll();

IS NULL 条件

$db->table('mytable')
   ->isNull('column1')
   ->findAll();

IS NOT NULL 条件

$db->table('mytable')
   ->notNull('column1')
   ->findAll();

多个条件

添加的条件通过 AND 连接。

$db->table('mytable')
    ->like('column2', '%mytable')
    ->gte('column1', 3)
    ->findAll();

如何创建 OR 条件

$db->table('mytable')
    ->beginOr()
    ->like('column2', '%mytable')
    ->gte('column1', 3)
    ->closeOr()
    ->eq('column5', 'titi')
    ->findAll();

调试

记录生成的查询

$db->getStatementHandler()->withLogging();

测量每个查询的时间

$db->getStatementHandler()->withStopWatch();

获取执行的查询数量

echo $db->getStatementHandler()->getNbQueries();

获取日志消息

print_r($db->getLogMessages());

大对象(LOBs)

插入文件

$db->largeObject('my_table')->insertFromFile('blobColumn', '/path/to/file', array('id' => 'something'));

从流中插入

$db->largeObject('my_table')->insertFromStream('blobColumn', $fd, array('id' => 'something'));

将大对象作为流获取(仅限 Postgres)

$fd = $db->largeObject('my_table')->eq('id', 'something')->findOneColumnAsStream('blobColumn');

将大对象作为字符串获取

echo $db->largeObject('my_table')->eq('id', 'something')->findOneColumnAsString('blobColumn');

驱动器

  • Postgres
    • 列类型:bytea
  • Sqlite 和 Mysql
    • 列类型:BLOB
    • PDO 不支持流功能(返回字符串而不是流)

哈希表(键/值存储)

如何将表用作键/值存储

$db->execute(
     'CREATE TABLE mytable (
         column1 TEXT NOT NULL UNIQUE,
         column2 TEXT default NULL
     )'
);

$db->table('mytable')->insert(['column1' => 'option1', 'column2' => 'value1']);

添加/替换一些值

$db->hashtable('mytable')
   ->columnKey('column1')
   ->columnValue('column2')
   ->put(['option1' => 'new value', 'option2' => 'value2']));

获取所有值

$result = $db->hashtable('mytable')->columnKey('column1')->columnValue('column2')->get();
print_r($result);

Array
(
    [option2] => value2
    [option1] => new value
)

$result = $db->hashtable('mytable')->getAll('column1', 'column2');

获取特定值

$db->hashtable('mytable')
   ->columnKey('column1')
   ->columnValue('column2')
   ->put(['option3' => 'value3']);

$result = $db->hashtable('mytable')
             ->columnKey('column1')
             ->columnValue('column2')
             ->get('option1', 'option3');

print_r($result);

Array
(
    [option1] => new value
    [option3] => value3
)

模式迁移

定义迁移

  • 迁移在名为 "Schema" 的命名空间内的简单函数中定义。
  • 将PDO实例传递给函数的第一个参数。
  • 函数名以版本号结尾。

示例

namespace Schema;

function version_1($pdo)
{
    $pdo->exec('
        CREATE TABLE users (
            id INTEGER PRIMARY KEY,
            name TEXT UNIQUE,
            email TEXT UNIQUE,
            password TEXT
        )
    ');
}


function version_2($pdo)
{
    $pdo->exec('
        CREATE TABLE tags (
            id INTEGER PRIMARY KEY,
            name TEXT UNIQUE
        )
    ');
}

自动运行模式更新

  • 方法check()执行所有迁移直到指定版本
  • 如果发生错误,事务将回滚
  • 在迁移过程中尽可能禁用外键检查

示例

$last_schema_version = 5;

$db = new PicoDb\Database(array(
    'driver' => 'sqlite',
    'filename' => '/tmp/mydb.sqlite'
));

if ($db->schema()->check($last_schema_version)) {

    // Do something...
}
else {

    die('Unable to migrate database schema.');
}

使用单例处理数据库实例

设置新的实例

PicoDb\Database::setInstance('myinstance', function() {

    $db = new PicoDb\Database(array(
        'driver' => 'sqlite',
        'filename' => DB_FILENAME
    ));

    if ($db->schema()->check(DB_VERSION)) {
        return $db;
    }
    else {
        die('Unable to migrate database schema.');
    }
});

在代码的任何地方获取此实例

PicoDb\Database::getInstance('myinstance')->table(...)