rain1 / pdo-powered
PDO 封装库,简化数据库交互
1.0.0
2024-04-23 20:17 UTC
Requires
- php: >= 8.1
- ext-json: *
- ext-pdo: *
Requires (Dev)
- phpunit/phpunit: ^11.0
This package is auto-updated.
Last update: 2024-09-23 21:06:23 UTC
README
PDOPowered 是一个提供以下功能的 PDO 封装库
- 延迟连接 仅在需要时创建 PDO 实例。配置凭据在连接后删除。
- 使用
$db->onConnect($closure)
在连接后执行操作。
- 使用
- 失败时重新连接 如果连接失败,则尝试重新连接(最多
PDOPowered::$MAX_TRY_CONNECTION
次尝试)。- 使用
$db->onConnectionFailure($closure)
在每次连接失败后执行操作(例如,休眠和/或错误报告)。
- 使用
- 快速查询参数 在
query
方法中调用 prepare 和 execute。$db->query("SELECT ?,?,?", [1,2,3])
- 查询方法返回一个带有增强方法的
PDOStatement
封装器。- fetchObjects 对每一行调用
fetchObject
并将结果存储在数组中。 - getPDOStatement 用于获取原生 PDOStatement。
- fetchObjects 对每一行调用
- 快速查询 提供快速查询的助手。
- 插入 用于快速插入
$db->insert("tableName",$arrayValues)
返回最后一个插入 ID。 - 更新 用于快速更新
$db->update("tableName", $valuesToUpdate, $arrayCondition)
返回受影响行数。 - insertOnDuplicateKeyUpdate 用于在重复键更新插入
$db->insertOnDuplicateKeyUpdate($tableName, $arrayValues)
返回最后一个插入 ID。 - 删除 用于快速删除
$db->delete("tableName", $arrayWhereCondition)
返回受影响行数。
- 插入 用于快速插入
- 简单调试 使用
$db->onDebug($closure)
可以访问调试输出并执行操作(例如,记录到文件、发送到标准输出等)。 - 访问原生 PDO 实例 通过扩展
PDOPowered
,您可以通过getPDO()
方法访问原生 PDO 实例。
基本用法
安装
composer require rain1/pdo-powered
或检出 https://github.com/LucaRainone/pdo-powered.git
或在此下载 (https://github.com/LucaRainone/pdo-powered/archive/master.zip)
开始使用
必须将 rain1\PDOPowered\Config\ConfigInterface 的实现传递给构造函数。我们提供以下实现
use \rain1\PDOPowered\Config\Config; $config = new Config("mysql", "user", "password", "localhost", 3306, "dbname", "utf8", [\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'']);
或等效
use \rain1\PDOPowered\Config\DSN; $config = new DSN( "mysql:host=localhost;port=3306;dbname=dbname;charset=utf8", "user", "password" ); $config->setOptions([\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'"]);
因此,我们以这种方式构建实例
$db = new PDOPowered($config);
可以使用预存在的 PDO 实例与 PDOPowered 一起使用。
$db = PDOPowered::buildFromPDOInstance($pdoInstance);
该库为插入/更新/删除和重复键更新提供了快捷方式。
// fast insert. Return the inserted id $id = $db->insert("tabletest", ['id'=>1, 'col1'=>'col1_1']); // fast update $db->update("tabletest", ['col1'=>'updated'], ['id'=>$id]); // build a "INSERT ON DUPLICATE KEY UPDATE" query $db->insertOnDuplicateKeyUpdate("tabletest", ['id'=> $id, 'col1'=>'updated']); $db->insertOnDuplicateKeyUpdate("tabletest", ['id'=> $id+1, 'col1'=>'updated']); // performs a delete $db->delete("tabletest", ['id'=>$id]); // simple query $row = $db->query("SELECT * FROM tabletest WHERE id = ?", [$id])->fetch(); // or equivalent $row = $db->query("SELECT * FROM tabletest WHERE id = :id", ['id'=>$id])->fetch();
query
方法返回 \PDOStatement 的封装器。可用的方法有:
fetch
fetchAll
fetchObject
fetchColumn
rowCount
closeCursor
getPDOStatement
返回原生 PDOStatement(用于任何情况)。fetchObjects
返回包含所有fetchObject
调用结果的数组。
高级用法
以下事件被触发:
- connectionFailure
- connect
- debug
// triggered after a connection fails: before the next attempt $db->onConnectionFailure(function($connectionTry, \Exception $exception) { sleep($connectionTry); error_log("Unable to connect on mysql: " . $exception->getMessage()); }); // triggered after a connection success $db->onConnect(function() { echo "Db connected\n"; }); // triggered on debug string $idDebugListener = $db->onDebug(function($debugType, \PDOStatement $PDOStatement = null, ...$args) { echo "$debugType\n"; if($PDOStatement) $PDOStatement->debugDumpParams(); echo "\n".json_encode($args); }); // for each event we can remove the listener $db->removeDebugListener($idDebugListener);
我们提供了一个简单的调试助手。
$db->onDebug(DebugParser::onParse(function ($info) { print_r($info); // info for timing, query, params and finalized query }));
其他选项
// set maximum number of connection attempts. \rain1\PDOPowered\Config\PDOPowered::$MAX_TRY_CONNECTION = 5; // set pdo attribute after connection. $db->setPDOAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
参数提示
PDOPowered 自动将值参数字符串视为 \PDO::PARAM_STR,将值整数视为 \PDO::PARAM_INT。对于任何情况,您都可以明确地这样做。
$users = $db->query( "SELECT * FROM user WHERE email = :email AND id = :id", [ "email" => new \rain1\PDOPowered\Param\ParamString("me@me.it"), "id"=> new \rain1\PDOPowered\Param\ParamInt("123"), ] )->fetchAll();
您可以使用每个 PDO Param 支持。
[ "param" => new \rain1\PDOPowered\Param\ParamNative("value", \PDO::PARAM_STR) ]
或构建自己的新参数类型,实现 \rain1\PDOPowered\Param\ParamInterface
。
例如,作为附加功能,我们有一个
[ "param" => new \rain1\PDOPowered\Param\ParamJSON(["key"=>"value"]) ]
这等价于
[ "param" => json_encode(["key"=>"value"]) ]
真实案例(在家试试)
您需要创建一个名为 "test" 的数据库。
use rain1\PDOPowered\Config\Config; use rain1\PDOPowered\Debug\DebugParser; use rain1\PDOPowered\Param\ParamJSON; use rain1\PDOPowered\Param\ParamString; use rain1\PDOPowered\PDOPowered; require "vendor/autoload.php"; function output(...$texts) { $endline = php_sapi_name() === "cli" ? "\n" : "<br/>"; foreach($texts as $text) echo str_replace("\n", $endline, $text) .$endline; } $config = new Config( "mysql", "root", "vagrant", "localhost", 3306, "test", "utf8", [ \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ] ); $db = new PDOPowered($config); output("adding listeners..."); $db->onConnectionFailure(function ($try, \Exception $e) { error_log("connection failed: " . $e->getMessage()); output("connection failed"); }); $db->onConnect(function() { output("Connected", ""); }); // only for debug $debug = 1; $countQuery = 0; $debug && $db->onDebug( DebugParser::onParse( function ($info) use (&$countQuery) { $str = "---- DEBUG ROW " . (++$countQuery) . " ----\n"; if (isset($info['query'])) $str .= $info['query']['demo'] . "\nexecution time: " . $info['query']['executionTime']; else $str .= $info['type'] . " " . json_encode($info['args']); output($str, ""); } ) ); output("set attributes"); $db->setPDOAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); output("first query"); $db->query("DROP TABLE IF EXISTS user"); $db->query("create table user ( id int auto_increment primary key, email varchar(32) null, settings text null ) ; "); $db->beginTransaction(); $id = $db->insert("user", ['email' => 'me@me.com']); $db->update("user", ["email" => "me2@me.com"], ['id' => (int)$id]); $db->delete("user", ['id' => 1]); $db->insert("user", [ 'id' => 1, 'email' => new ParamString("me@me.com") ]); $db->insertOnDuplicateKeyUpdate("user", [ 'id' => 1, 'email' => new ParamString("me3@me.com"), 'settings' => new ParamJSON(['privacy' => 1, 'newsletter' => 'no']) ]); $rows = $db->query("SELECT * FROM user WHERE id = :id", ['id' => 1])->fetchAll(); $db->commitTransaction(); $db->query("SELECT SLEEP (1)"); print_r($rows);