charm/db

PDO 包装器,适用于那些不喜欢冗长的 `PDOStatement` 方法但又不喜欢 SQL 注入的人。

0.0.12 2021-07-16 15:09 UTC

This package is auto-updated.

Last update: 2024-09-09 17:20:06 UTC


README

Charm\DB 是围绕 PDO 的一种非常薄的包装器。它存在的唯一原因是我讨厌多次编写大量代码。

它与使用 PDO 的框架(如 Doctrine 或 Symfony)配合得很好,这对于你正在编写库且不想让库依赖于 Doctrine 来说是很不错的。

我已经为不同的项目编写了这种类型的包装器多次。所以我最终决定编写一些文档并将其放在 Packagist 上 - 主要是为了让自己更容易安装。:-D

懒惰读者的示例

  • Charm\DB 查询

     $rows = $db->query('SELECT * FROM users WHERE id = ?', [ 123 ] );
    
  • PDO 查询

     $stmt = $db->prepare('SELECT * FROM users WHERE id = ?', [ 123 ] );
     $stmt->execute([123]);
     $rows = $stmt->fetchAll(PDO::FETCH_CLASS);
    
  • Charm\DB 执行

     $affectedRows = $db->exec('DELETE FROM trash WHERE age < ?', [ gmdate('Y-m-d H:i:s') ]);
    
  • PDO 执行

     $stmt = $db->prepare('DELETE FROM trash WHERE age < ?');
     $stmt->execute([ gmdate('Y-m-d H:i:s') ]);
     $affectedRows = $stmt->rowCount();
    
  • PDO 对于懒惰的人来说,容易因为人为错误导致巨大的安全问题

     $affectedRows = $db->exec('DELETE FROM trash WHERE age < '.$db->quote(gmdate('Y-m-d H:i:s')));
    
  • 没有特殊的方法来获取单行,只需使用 ->current()

     $row = $db->query('SELECT * FROM users WHERE id = ?', [123])->current();
    
  • 没有特殊的方法来获取单列,只需提供列号。

     $usernames = $db->query('SELECT username FROM users', [], 0);
    
  • 获取单个字段,只需使用列 0 和 ->current() 再次。

     $value = $db->query('SELECT username FROM users WHERE id = ? LIMIT 1', [123], 0)->current();
    

有时你可能想要使用 PDO API 提供的额外功能。有两个方法相关

  • $db->prepare( string $statement, array $driver_options = array() )PDO::prepare() 方法完全相同,但具有语句缓存。

  • $db->pdo(): ?PDO 返回原生 PDO 实例。

使用方法

连接到数据库(使用 PDO DSN 字符串)。

$db = Charm\DB::__construct ( string $dsn, string $username = ?, string $passwd = ?, array $options = ? )

或包装现有的 PDO 实例

$db = Charm\DB::wrap ( PDO $pdoInstance ) : Charm\DB;

使用内置的工厂

在 PHP 世界中,似乎有无数种方法可以让人们使框架应用程序的配置“容易”。我们必须学习如何将配置注入到另一个将被注入另一个工具的配置中。但只有在你配置了自动装配的情况下,才会进行注入。

当你在构建你相信将成为 Facebook 和乔治亚州“Johnny Inc.”的首席开发者 Johnny 所喜爱的框架时,这都是可以理解的。我更喜欢在我(如果)从最初开始的结构中成长起来时重构我的代码。

我们开发者不断地设计最复杂的结构,以使配置东西变得容易。

但如果你没有时间做这件事,Charm* 组件通常允许你通过公共静态属性来配置它们,然后你可以通过它们的 ::instance() 静态方法检索实例。

Charm\DB::instance() 可以通过以下方式配置

    // Either put in some configuration:

    Charm\DB::$dsn          = $dsn;
    Charm\DB::$username     = ?;
    Charm\DB::$passwd       = ?;
    Charm\DB::$options      = ?;

    // Or provide an instance directly

    Charm\DB::$instance     = $pdoInstance;

现在,你可以通过 Charm\DB::instance() 在整个项目中访问数据库。

如果这不适合你,你可以继续设置 Symfony 或设计你自己的方法来构建它。

`Charm\DB::query (

更多示例,本质上与 TLDR 标题下的上述示例相同。

查询数据

数据库查询通过 $db->query()$db->column() 完成。

// Multiple rows returns an iterable
$users = $db->query('SELECTFROM users WHERE last_login < ?', [gmdate('Y-m-d H:i:s')]);

// Single rows can be fetched this way (sending 'LIMIT 1' is kind to your database engine)
$user = $db->query('SELECTFROM users WHERE username = ? LIMIT 1', [ $username ])->current();

// Fetch a single column
$usernames = $db->column('SELECT username FROM users);

// Fetcha single value
$numberOfUsers = $db->column('SELECT COUNT(*) FROM users')->current();

定义、操作、控制

所有对数据库的修改都通过 $db->exec() 函数完成。

// Insert a row into a table
if ($db->exec('INSERT INTO users (username, password ) VALUES (?, ?)', [ $username, $password ])) {
    echo "Created a new user with id ".$db->lastInsertId()."!\n";
}

// Delete some data
if ($count = $db->exec('DELETE FROM users WHERE expires_date < ?', [ gmdate('Y-m-d H:i:s') ])) {
    echo "Deleted $count users\n";
}

错误处理

包装器默认为 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,所以你会收到标准的 PDO 异常。

对这种包装器的无效使用将触发带有错误代码的 Charm\DB\Error 异常(根据类常量)。如果你没有使用 PDO::ERRMODE_EXCEPTION,我们只会抛出 Charm\DB\Error 异常。

当最后一次错误被触发时发出的查询可用在 $db->lastFailedQuery

安全

此类不提供任何安全功能,但它使你更容易进行更安全的数据库查询。

此类重写了__debugInfo()魔术方法,以避免意外泄露机密,但通常情况下,你绝不应该在生产环境中显示原始的错误信息。