voku / simple-mysqli
简单 MySQLi 库
Requires
- php: >=7.0
- ext-mysqli: *
- symfony/property-access: ~2.8 || ~3.3 || ~4.0 || ~5.0 || ~6.0
- voku/arrayy: ~6.0 || ~7.0
- voku/phonetic-algorithms: ~5.0
- voku/portable-utf8: ~6.0
- voku/simple-cache: ~4.0
Requires (Dev)
- doctrine/dbal: ~2.0 || ~3.0
- phpunit/phpunit: ~6.0 || ~7.0 || ~9.0
- dev-master
- 8.3.1
- 8.3.0
- 8.2.10
- 8.2.9
- 8.2.8
- 8.2.7
- 8.2.6
- 8.2.5
- 8.2.4
- 8.2.3
- 8.2.2
- 8.2.1
- 8.2.0
- 8.1.0
- 8.0.6
- 8.0.5
- 8.0.4
- 8.0.3
- 8.0.2
- 8.0.1
- 8.0.0
- 7.4.1
- 7.4.0
- 7.3.0
- 7.2.1
- 7.2.0
- 7.1.4
- 7.1.3
- 7.1.2
- 7.1.1
- 7.1.0
- 7.0.2
- 7.0.1
- 7.0.0
- 6.1.1
- 6.1.0
- v6.0.3
- v6.0.2
- v6.0.1
- v6.0.0
- v5.4.8
- v5.4.7
- v5.4.6
- v5.4.5
- v5.4.4
- v5.4.3
- v5.4.2
- v5.4.1
- v5.4.0
- v5.3.1
- v5.3.0
- v5.2.1
- v5.2.0
- v5.1.0
- v5.0.1
- v5.0.0
- v4.4.3
- v4.4.2
- v4.4.1
- v4.4.0
- v4.3.1
- v4.3.0
- v4.2.6
- v4.2.5
- v4.2.4
- v4.2.3
- v4.2.2
- v4.2.1
- v4.2.0
- v4.1.2
- v4.1.1
- v4.1.0
- v4.0.1
- v4.0.0
- v3.0.4
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0.0
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.9.0
- v1.8.27
- v1.8.26
- v1.8.25
- v1.8.24
- v1.8.23
- v1.8.22
- v1.8.21
- v1.8.20
- v1.8.19
- v1.8.18
- v1.8.17
- v1.8.16
- v1.8.15
- v1.8.14
- v1.8.13
- v1.8.12
- v1.8.11
- v1.8.10
- v1.8.9
- v1.8.8
- v1.8.7
- v1.8.6
- v1.8.5
- v1.8.4
- v1.8.3
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.1
- v1.7.0
- v1.6.1
- v1.6.0
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5
- v1.4
- v1.3
- v1.2
- v1.1
- 1
- 0.9
- dev-analysis-Pxbo1e
- dev-dependabot/add-v2-config-file
- dev-whitesource/configure
- dev-analysis-8wod4W
- dev-analysis-qxog2y
- dev-analysis-8me2x7
- dev-analysis-qgQ4mw
- dev-analysis-XWApWP
- dev-analysis-q1AQKN
- dev-php_old
This package is auto-updated.
Last update: 2024-09-04 02:13:27 UTC
README
💎 简单 MySQLi 类
这是一个与 PHP 7+ 和 PHP 8.0 兼容的简单 MySQL 抽象层,它使用 mysqli_* 函数在核心处提供简单且 安全 的数据库交互。这对于像 cron 作业、facebook canvas 活动、微型框架或网站等小型应用非常理想。
你还可以使用 💍 "Simple Active Record" 类,它基于此数据库类并添加了一些面向对象的语法。但在使用之前,请了解“Active Record”与“数据映射器”之间的区别。
获取 "Simple MySQLi"
你可以在此处下载,或者使用 composer 安装。
{ "require": { "voku/simple-mysqli": "8.*" } }
通过 "composer require" 安装
composer require voku/simple-mysqli
启动驱动器
use voku\db\DB; require_once 'composer/autoload.php'; $db = DB::getInstance('yourDbHost', 'yourDbUser', 'yourDbPassword', 'yourDbName'); // example // $db = DB::getInstance('localhost', 'root', '', 'test');
多例 && 单例
你可以无参数地使用 DB::getInstance()
并获取你的(作为“单例”)第一个初始化的连接。或者,你可以更改参数,这样你将创建一个新的“多例”实例,它的工作方式类似于单例,但你需要再次使用相同的参数,否则(没有相同的参数)你会得到一个新的实例。
Doctrine/DBAL 作为父驱动器
use voku\db\DB; require_once 'composer/autoload.php'; $connectionParams = [ 'dbname' => 'yourDbName', 'user' => 'yourDbUser', 'password' => 'yourDbPassword', 'host' => 'yourDbHost', 'driver' => 'mysqli', // 'pdo_mysql' || 'mysqli' 'charset' => 'utf8mb4', ]; $config = new \Doctrine\DBAL\Configuration(); $doctrineConnection = \Doctrine\DBAL\DriverManager::getConnection( $connectionParams, $config ); $doctrineConnection->connect(); $db = DB::getInstanceDoctrineHelper($doctrineConnection);
使用 "DB" 类
使用此库有无数种方式,这里有一些最常见方法的示例。
从表中选择和检索数据
use voku\db\DB; $db = DB::getInstance(); $result = $db->query("SELECT * FROM users"); $users = $result->fetchAll();
但你也可以使用一个方法进行选择查询
$db->select(string $table, array $where); // generate an SELECT query
示例:选择
$where = [ 'page_type =' => 'article', 'page_type NOT LIKE' => '%öäü123', 'page_id >=' => 2, ]; $articles = $db->select('page', $where); echo 'There are ' . count($articles) . ' article(s):' . PHP_EOL; foreach ($articles as $article) { echo 'Type: ' . $article['page_type'] . PHP_EOL; echo 'ID: ' . $article['page_id'] . PHP_EOL; }
下面是 "WHERE" 数组的连接器列表:"NOT","IS","IS NOT","IN","NOT IN","BETWEEN","NOT BETWEEN","LIKE","NOT LIKE",">","<",">=","<=","<>","+","-"
INFO:将数组用作 "[NOT] IN" 和 "[NOT] BETWEEN" 的 $value
INFO:在值中使用 + / - 而不是在 $data 的键中使用
示例:使用 "page_template = page_template + 1" 的 UPDATE
$where = [ 'page_type LIKE' => '%foo', 'page_type NOT LIKE' => 'bar', ]; $data = [ 'page_template' => ['page_template +' => 1], 'page_type' => 'lall', ]; $resultSelect = $db->update('page', $data, $where);
示例:使用 "NOT IN" 的 SELECT
$where = [ 'page_type NOT IN' => [ 'foo', 'bar' ], 'page_id >' => 2, ]; $resultSelect = $db->select('page', $where);
示例:使用缓存的 SELECT
$resultSelect = $db->execSQL("SELECT * FROM users", true, 3600);
结果(通过 $result->fetchAllArray())仅在查询为 SELECT 语句时缓存 3600 秒,否则你将得到来自 $db->query() 函数的默认结果。
在表中插入数据
要操纵表,你可以使用最基本的方法封装,它们的工作方式都相同:解析键/值对的数组并形成安全的查询
这些方法是
$db->insert( string $table, array $data ); // generate an INSERT query $db->replace( string $table, array $data ); // generate an REPLACE query $db->update( string $table, array $data, array $where ); // generate an UPDATE query $db->delete( string $table, array $where ); // generate a DELETE query
所有方法都将返回结果 mysqli_insert_id() 或根据上下文返回 true/false。正确的方法是始终检查它们是否成功执行,总是返回正确的结果
示例:DELETE
$deleteArray = ['user_id' => 9]; $ok = $db->delete('users', $deleteArray); if ($ok) { echo "user deleted!"; } else { echo "can't delete user!"; }
注意:在执行之前,所有参数值都会进行清理,你不需要事先转义值。
示例:INSERT
$insertArray = [ 'name' => "John", 'email' => "johnsmith@email.com", 'group' => 1, 'active' => true, ]; $newUserId = $db->insert('users', $insertArray); if ($newUserId) { echo "new user inserted with the id $new_user_id"; }
示例:REPLACE
$replaceArray = [ 'name' => 'lars', 'email' => 'lars@moelleken.org', 'group' => 0 ]; $tmpId = $db->replace('users', $replaceArray);
在查询中绑定参数
绑定参数是防止MySQL注入的有效方法,因为在执行之前参数都会被清理。
$sql = "SELECT * FROM users WHERE id_user = :id_user AND active = :active LIMIT 1 "; $result = $db->query($sql, ['id_user' => 11, 'active' => 1]); if ($result) { $user = $result->fetchArray(); print_r($user); } else { echo "user not found"; }
事务
使用begin()
、commit()
和rollback()
来管理事务
$db->beginTransaction(); $db->query( 'UPDATE `users` SET `foo` = :foo WHERE id = :id', ['foo' => 100, 'id' => 1] ); $db->query( 'UPDATE `users_noop` SET `foo` = :foo WHERE id = :id', ['foo' => 100, 'id' => 2] ); $db->endTransaction();
在begin()
和commit()
之间的任何SQL错误都会引发一个RuntimeException
。
您还可以使用DB->transact()
方法。以下代码与上述代码等效
$db->transact(function($db) { $db->query( 'UPDATE `users` SET `foo` = :foo WHERE id = :id', ['foo' => 100, 'id' => 1] ); $db->query( 'UPDATE `users_noop` SET `foo` = :foo WHERE id = :id', ['foo' => 100, 'id' => 2] ); });
使用 "Result" 类
执行一个SELECT
查询后,您将收到一个Result
对象,该对象可以帮助您操作结果数据。有不同方式访问这些数据,请查看下面的示例
获取所有数据
$result = $db->query("SELECT * FROM users"); $allUsers = $result->fetchAll();
获取所有数据与Result::RESULT_TYPE_*工作相同,fetchAll()
和fetch()
方法将返回默认值,基于$_default_result_type
配置。其他方法包括
$row = $result->fetch(); // fetch an single result row as defined by the config (array, object or Arrayy) $row = $result->fetchArray(); // fetch an single result row as array $row = $result->fetchArrayy(); // fetch an single result row as Arrayy object $row = $result->fetchObject(); // fetch an single result row as object $row = $result->fetchYield(); // fetch an single result row as Generator $data = $result->fetchAll(); // fetch all result data as defined by the config (array, object or Arrayy) $data = $result->fetchAllArray(); // fetch all result data as array $data = $result->fetchAllArrayy(); // fetch all result data as Array object $data = $result->fetchAllObject(); // fetch all result data as object $data = $result->fetchAllYield(); // fetch all result data as Generator $data = $result->fetchColumn(string $column, bool $skipNullValues); // fetch a single column as string $data = $result->fetchAllColumn(string $column, bool $skipNullValues); // fetch a single column as an 1-dimension array $data = $result->fetchArrayPair(string $key, string $value); // fetch data as a key/value pair array
获取数据库表字段
返回结果集中的字段信息行
$fields = $result->fetchFields();
如果您想以关联数组的形式返回每个字段信息,请将true
作为参数传递。默认情况下,每个字段信息都以对象返回,这与mysqli_fetch_fields
函数完全相同。
获取 + 可调用
获取一行或行内的单个列
$data = $result->fetch($row_number, $column);
此方法构成了所有fetch_方法的基础。所有形式的fetch_都将内部行指针向前移动到下一行。如果没有更多的行可以获取,将返回null
。
获取 + 转置
一次性返回所有行,转置为二维数组
$plan_details = $plans->fetchTranspose();
转置具有X行和Y列的结果集将导致一个二维数组,其中每个Y行包含X列。
将列名作为参数传递,以返回每个列作为包含键的关联数组,键来自提供的列值。如果没有提供,则键将从零开始为数字。
例如
$transposedExample = [ 'title' => [ 1 => 'Title #1', 2 => 'Title #2', 3 => 'Title #3', ], );
获取 + 对
一次性将所有行作为键值对返回,使用第一个参数中的列作为键
$countries = $result->fetchPairs('id');
将列名作为第二个参数传递,以仅返回每个对中的单个列作为值
$countries = $result->fetchPairs('id', 'name'); /* [ 1 => 'Title #1', 2 => 'Title #2', 3 => 'Title #3', ] */
获取 + 组
一次性将所有行作为分组数组返回
$students_grouped_by_gender = $result->fetchGroups('gender');
将列名作为第二个参数传递,以仅返回每个组中的单个列作为值
$student_names_grouped_by_gender = $result->fetchGroups('gender', 'name');
获取 + 第一个
从结果中返回第一行元素
$first = $result->first();
将列名作为参数传递,以返回第一行中的单个列
$name = $result->first('name');
获取 + 最后一个
从结果中返回最后一行元素
$last = $result->last();
将列名作为参数传递,以返回最后一行中的单个列
$name = $result->last('name');
获取 + 范围
从结果中返回行切片
$slice = $result->slice(1, 10);
上述代码将返回10行,跳过第一行。第一个参数是零基于偏移量;第二个参数是要求数量;第三个参数是布尔值,表示是否保留键(可选,默认为false)。此方法基本上与PHP内置的array_slice()
函数的行为相同。
获取 + 映射
设置用于Result->fetchCallable()
方法内的回调函数的映射器
$result->map(function($row) { return (object) $row; }); $object = $result->fetchCallable(0);
上述示例将结果中的一个行(0)映射到一个对象。将映射回调函数设置为null以禁用它。
获取 + 别名
$db->get() // alias for $db->fetch(); $db->getAll() // alias for $db->fetchAll(); $db->getObject() // alias for $db->fetchAllObject(); $db->getArray() // alias for $db->fetchAllArray(); $db->getArrayy() // alias for $db->fetchAllArrayy(); $db->getYield() // alias for $db->fetchAllYield(); $db->getColumn($key) // alias for $db->fetchColumn($key);
获取 + 迭代
要迭代结果集,可以使用上面列出的任何fetch()方法。
$result = $db->select('users'); // using while while ($row = $result->fetch()) { echo $row->name; echo $row->email; } // using foreach (via "fetchAllObject()") foreach($result->fetchAllObject() as $row) { echo $row->name; echo $row->email; } // using foreach (via "Result"-object) foreach($result as $row) { echo $row->name; echo $row->email; } // using foreach (via "Generator"-object) foreach($result->fetchAllYield() as $row) { echo $row->name; echo $row->email; } // INFO: "while + fetch()" and "fetchAllYield()" will use less memory that "foreach + "fetchAllObject()", because we will fetch each result entry seperatly
执行多查询
要执行多个查询,可以使用$db->multi_query()
方法。您可以使用分号;
分隔多个查询。
返回类型
- 通过
SELECT
查询返回"Result"-Array - 仅通过
INSERT
查询返回"bool" - 仅通过(affected_rows)通过
UPDATE / DELETE
查询返回"bool" - 仅通过例如"DROP"查询返回"bool"
例如
$sql = " INSERT INTO foo SET page_template = 'lall1', page_type = 'test1'; INSERT INTO lall SET page_template = 'lall2', page_type = 'test2'; INSERT INTO bar SET page_template = 'lall3', page_type = 'test3'; "; $result = $this->db->multi_query($sql); // true $sql = " SELECT * FROM foo; SELECT * FROM lall; SELECT * FROM bar; "; $result = $this->db->multi_query($sql); // Result[] foreach ($result as $resultForEach) { $tmpArray = $resultForEach->fetchArray(); ... }
使用 "Prepare" 类
预处理语句的优点是它们在MySQL-Server中一起构建,因此性能更好。
但调试更难,日志记录不可能(通过PHP),因此我们添加了一个名为"bind_param_debug"的"bind_param"包装器。使用此包装器,我们通过PHP预先构建SQL查询(仅用于调试/记录)。现在您可以将查询echo。
INFO:您仍然可以使用"bind_param"而不是"bind_param_debug",例如,如果您需要更好的性能。
INSERT-Prepare-Query (示例)
use voku\db\DB; $db = DB::getInstance(); // ------------- // prepare the queries $query = 'INSERT INTO users SET name = ?, email = ? '; $prepare = $db->prepare($query); $name = ''; $email = ''; $prepare->bind_param_debug('ss', $name, $email); // ------------- // execute query no. 1 // INFO: "$template" and "$type" are references, since we use "bind_param" or "bind_param_debug" $name = 'name_1_中'; $email = 'foo@bar.com'; $prepare->execute(); // DEBUG echo $prepare->get_sql_with_bound_parameters(); // ------------- // execute query no. 2 // INFO: "$template" and "$type" are references, since we use "bind_param" or "bind_param_debug" $name = 'Lars'; $email = 'lars@moelleken.org'; $prepare->execute(); // DEBUG echo $prepare->get_sql_with_bound_parameters();
SELECT-Prepare-Query (示例)
use voku\db\DB; $db = DB::getInstance(); // ------------- // insert some dummy-data, first $data = [ 'page_template' => 'tpl_test_new123123', 'page_type' => 'ö\'ä"ü', ]; // will return the auto-increment value of the new row $resultInsert[1] = $db->insert($this->tableName, $data); $resultInsert[2] = $db->insert($this->tableName, $data); // ------------- // prepare the queries $sql = 'SELECT * FROM ' . $this->tableName . ' WHERE page_id = ? '; $prepare = $this->db->prepare($sql); $page_id = 0; $prepare->bind_param_debug('i', $page_id); // ------------- // execute query no. 1 $page_id = $resultInsert[1]; $result = $prepare->execute(); $data = $result->fetchArray(); // $data['page_template'] === 'tpl_test_new123123' // $data['page_id'] === $page_id // ------------- // execute query no. 2 $page_id = $resultInsert[2]; $result = $prepare->execute(); $data = $result->fetchArray(); // $data['page_id'] === $page_id // $data['page_template'] === 'tpl_test_new123123'
日志和错误
您可以将钩子插入到“DB”类中,这样您就可以使用您自己的“Logger”类。但您必须覆盖这些方法。
$this->trace(string $text, string $name) { ... } $this->debug(string $text, string $name) { ... } $this->info(string $text, string $name) { ... } $this->warn(string $text, string $name) { ... } $this->error(string $text, string $name) { ... } $this->fatal(string $text, string $name) { ... }
您还可以通过“DB”类的“getInstance()”参数“logger_level”禁用每个sql查询的记录。如果您将“logger_level”设置为除“TRACE”或“DEBUG”之外的其他值,则“DB”类将仅记录错误。
DB::getInstance( getConfig('db', 'hostname'), // hostname getConfig('db', 'username'), // username getConfig('db', 'password'), // password getConfig('db', 'database'), // database getConfig('db', 'port'), // port getConfig('db', 'charset'), // charset true, // exit_on_error true, // echo_on_error 'cms\Logger', // logger_class_name getConfig('logger', 'level'), // logger_level | 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL' getConfig('session', 'db') // session_to_db );
显示查询日志:日志包含执行的SQL语句、执行时间和结果行数。
print_r($db->log());
要调试mysql错误,请使用$db->errors()
获取所有错误(如果没有错误则返回false)或使用$db->lastError()
获取关于最后一个错误的详细信息。
if ($db->errors()) { echo $db->lastError(); }
但最简单的调试方法是配置“DB”类,通过“DB::getInstance()”显示错误并在错误时退出(请参见上面的示例)。现在,如果您在“localhost”上工作,您可以在浏览器中看到SQL错误;或者您可以通过一个简单的函数实现自己的“checkForDev()”,而无需扩展“Debug”类。如果您将通过电子邮件接收错误信息,则可以代替扩展“Debug”类实现自己的“mailToAdmin()”函数。
更新日志
请参阅CHANGELOG.md。
支持
有关支持和捐款,请访问Github | 问题 | PayPal | Patreon。
有关状态更新和发布公告,请访问发布 | Twitter | Patreon。
如需专业支持,请联系我。
感谢
- 感谢GitHub(微软)提供代码托管和良好的基础设施,包括问题管理等。
- 感谢IntelliJ,他们制作了最好的PHP IDE,并为我提供了PhpStorm的开源许可!
- 感谢Travis CI,它是最好的、最简单的持续集成工具!
- 感谢StyleCI提供的简单但强大的代码风格检查。
- 感谢PHPStan 和 Psalm,它们提供了真正出色的静态分析工具,并帮助发现代码中的错误!