sw897/easydb

易于使用的数据库抽象层

1.1 2017-11-29 05:02 UTC

This package is not auto-updated.

Last update: 2024-09-20 01:23:23 UTC


README

Build Status Latest Stable Version Latest Unstable Version License Downloads

PDO 缺乏简洁性;EasyDB 使将数据与指令分离变得容易(且美观)。

EasyDB 由 Paragon Initiative Enterprises 创建,作为我们鼓励更好的 应用安全 实践的一部分。

也请查看我们的其他 开源项目

安装 EasyDB

首先,如果您还没有使用,请 获取 Composer

接下来,运行以下命令

/path/to/your/local/composer.phar require paragonie/easydb:^2

如果您已将 Composer 安装在 /usr/bin,可以将 /path/to/your/local/composer.phar 替换为仅为 composer

为什么使用 EasyDB?因为它更干净!

让我们重构一个危险的 PHP 片段,它之前使用字符串连接传递用户输入而不是使用预处理语句。例如,想象一下只是将 {$_GET['blogpostid']} 放在 mysql_query() 语句的中间。让我们使其更安全。

PDO 方法

$db = new \PDO(
    'mysql:host=localhost;dbname=something',
    'username',
    'putastrongpasswordhere'
);

$statement = $db->prepare('SELECT * FROM comments WHERE blogpostid = ? ORDER BY created ASC');
$exec = $statement->execute([$_GET['blogpostid']]);
$rows = $exec->fetchAll(\PDO::FETCH_ASSOC);
foreach ($rows as $row) {
    $template_engine->render('comment', $row);
}

对于这样一个简单的任务来说,这有点冗长。如果我们这样做多个地方,我们会重复很多次。

EasyDB 解决方案

$db = \EasyDB\Factory::create(
    'mysql:host=localhost;dbname=something',
    'username',
    'putastrongpasswordhere'
);

$rows = $db->run('SELECT * FROM comments WHERE blogpostid = ? ORDER BY created ASC', $_GET['blogpostid']);
foreach ($rows as $row) {
    $template_engine->render('comment', $row);
}

我们将其变成了一行。

EasyDB 还能快速做什么?

向数据库表插入一行

$db->insert('comments', [
    'blogpostid' => $_POST['blogpost'],
    'userid' => $_SESSION['user'],
    'comment' => $_POST['body'],
    'parent' => isset($_POST['replyTo']) ? $_POST['replyTo'] : null
]);

构建插入语句而不执行

$sql = $db->buildInsertQuery('comments', [
    'blogpostid',
    'userid',
    'comment'
]);

// INSERT INTO comments (blogpostid, userid, comment) VALUES (?, ?, ?)

$result = $db->q(
    $sql,
    $values,
    \PDO::FETCH_BOTH,
    true
);

更新数据库表中的一行

$db->update('comments', [
    'approved' => true
], [
    'commentid' => $_POST['comment']
]);

从数据库表中删除一行

// Delete all of this user's comments
$db->delete('comments', [
    'userid' => 3
]);

从表中获取单行

$userData = $db->row(
    "SELECT * FROM users WHERE userid = ?",
    $_GET['userid']
);

从单行中获取单个列

$exists = $db->cell(
    "SELECT count(id) FROM users WHERE email = ?",
    $_POST['email']
);
/* OR YOU CAN CALL IT THIS WAY: */
$exists = $db->single(
    "SELECT count(id) FROM users WHERE email = ?", 
    array(
        $_POST['email'] 
    )
);

尝试执行事务

$save = function (EasyDB $db) use ($userData, $query) {
    $db->safeQuery($query, [$userData['userId']]);
    \Some\Other\Package::CleanUpTable($db);
};
// auto starts, commits and rolls back a transaction as necessary
$db->tryFlatTransaction($save);

生成动态查询条件

$statement = EasyStatement::open()
    ->with('last_login IS NOT NULL');

if (strpos($_POST['search'], '@') !== false) {
    // Perform a username search
    $statement->orWith('username LIKE ?', '%' . $db->escapeLikeValue($_POST['search']) . '%');
} else {
    // Perform an email search
    $statement->orWith('email = ?', $_POST['search']);
}

// The statement can compile itself to a string with placeholders:
echo $statement; /* last_login IS NOT NULL OR username LIKE ? */

// All the values passed to the statement are captured and can be used for querying:
$user = $db->single("SELECT * FROM users WHERE $statement", $statement->values());

注意:带有条件的值传递完全是可选的,但建议使用。

可变数量的 "IN" 参数

// Statements also handle translation for IN conditions with variable arguments,
// using a special ?* placeholder:
$roles = [1];
if ($_GET['with_managers']) {
    $roles[] = 2;
}

$statement = EasyStatement::open()->in('role IN (?*)', $roles);

// The ?* placeholder is replaced by the correct number of ? placeholders:
echo $statement; /* role IN (?, ?) */

// And the values will be unpacked accordingly:
print_r($statement->values()); /* [1, 2] */

条件分组

// Statements can also be grouped when necessary:
$statement = EasyStatement::open()
    ->group()
        ->with('subtotal > ?')
        ->andWith('taxes > ?')
    ->end()
    ->orGroup()
        ->with('cost > ?')
        ->andWith('cancelled = 1')
    ->end();

echo $statement; /* (subtotal > ? AND taxes > ?) OR (cost > ? AND cancelled = 1) */

如果我需要特定于 PDO 的功能怎么办?

$pdo = $db->getPdo();

我可以为现有的 PDO 实例创建 EasyDB 包装器吗?

是的! 这就像这样做

$easy = new \EasyDB\EasyDB($pdo, 'mysql');

我该如何运行测试?

vendor/bin/phpunit