ambalus / dbsimple
用于与各种数据库交互的接口。
Requires
- php: >=5.6
This package is not auto-updated.
Last update: 2024-09-29 02:13:31 UTC
README
DbSimple:与各种关系型数据库交互的最简单但功能强大的接口。(C) Dmitry Koterov, http://en.dklab.ru/lib/DbSimple/
摘要
有许多PHP库为我们提供了统一的数据库访问接口:PEAR DB、ADOdb 和 PDO。使用这些库编写的代码通常非常冗长,并且被无用的细节过度加载。DbSimple 引入了一个比上述(以及许多其他流行)抽象库都要简单易用的接口。
主要功能
- 支持PHP 5,DBMS:MySQL、PostgreSQL、InterBase/FireBird。
- 简单简洁的接口(请见以下示例)。
- SQL体中的条件宏块({}-块),允许动态生成甚至非常复杂的查询,而不会损害代码的可读性。
- 查询结果缓存(如有必要)。
- 支持各种占位符(查询参数)类型:基于列表、关联、基于标识符等。
- 支持“select + 计算总行数”操作(用于分页显示的数据)。
- 直接获取结果的功能:所有结果行、一行、一列、一个单元格、关联数组、多维关联数组、链接树等。
- 非常方便的接口用于监视和调试查询错误。
- 支持增强的查询日志(包括查询结果和调用者行号)。
- 支持“原生”数据库占位符和自动优化“单次准备,多次执行”。
- 基于对象的BLOB访问接口(如有必要)。
- 库代码相当紧凑:一个文件是基类,一个文件是特定数据库驱动程序。
理念
- 许可证LGPL(开源)。
- 库不应封装不同DBMS之间SQL语言的差异。
- 接口必须非常简洁,便于实际使用。
- “查询执行”和“结果获取”必须合并为单一操作。
- 如果查询是“逐块”构建的(通过PHP代码动态进行),则不应损害可读性。
- “单次准备,多次执行”优化必须透明地自动执行。
为什么不使用其他库?
- PEAR DB、ADOdb:这些库并没有简化DBMS访问,它们只是提供了单一(且过重)的访问接口;调试功能太差。
- PDO:需要PHP 5;处理占位符和查询结果不太方便。
- 标准的PHP数据库访问函数:代码可读性差,调试困难,容易受到SQL注入攻击。
库接口(概述)
mixed connect(string $dsn) 使用DSN语法连接任何数据库的静态函数。
mixed select(string $query [,$arg1...]) 执行查询并返回2D数组的结果。
hash selectRow(string $query [,$arg1...]) 获取单行查询的结果。
array selectCol(string $query [,$arg1...]) 获取一列。
scalar selectCell(string $query [,$arg1...]) 获取一个查询结果单元格。
mixed selectPage(int &$total, string $query [,$arg1...) 获取包含计算找到的行总数的2D数组。
mixed query(string $query [,$arg1...]) 执行非SELECT查询;对于自增字段和INSERT查询,返回最后一个插入的ID。
mixed transaction([mixed $parameters]) 开始新的事务。
mixed commit() / mixed rollback() 提交/回滚当前事务。
此外,您还可以使用保留的列别名(ARRAY_KEY*等)和属性SQL注释(例如,用于启用缓存)来修改结果表示的格式。请参见以下使用示例。
概要
添加到您的 composer.json 文件中
"require": { "dklab/dbsimple": "dev-master" }, "repositories":[ { "type": "git", "url": "https://github.com/Ambalus/DbSimple.git" } ]
列表 1:连接到数据库管理系统
require_once './vendor/autoload.php'; $DB = DbSimple\Generic::connect("pgsql://login:password@host/database");
或者
require_once './vendor/autoload.php'; $DB = new DbSimple\Connect("pgsql://login:password@host/database");
或者
您可以使用 PDO DSN 语法(当前仅支持 MySQL 提供商的套接字连接)
require_once './vendor/autoload.php'; $DB = new DbSimple\Connect("mysqli:unix_socket=/cloudsql/app:instance;user=root;pass=;dbname=testdb");
列表 2:获取所有结果行
$rows = $DB->select('SELECT * FROM ?_user LIMIT 10'); foreach ($rows as $numRow => $row) { echo $row['user_name']; }
列表 3:获取一页
// Variable $totalNumberOfUsers will hold total number of found rows. $rows = $DB->selectPage( $totalNumberOfUsers, 'SELECT * FROM ?_user LIMIT ?d, ?d', $pageOffset, $numUsersOnPage );
列表 4:SQL 查询中的宏替换
$rows = $DB->select(' SELECT * FROM goods WHERE category_id = ? { AND activated_at > ? } LIMIT ?d ', $categoryId, (empty($_POST['activated_at'])? DBSIMPLE_SKIP : $_POST['activated_at']), $pageSize );
列表 5:SQL 查询中的宏替换 #2
$rows = $DB->select(' SELECT * FROM goods g { JOIN category c ON c.id = g.category_id AND 1 = ? } WHERE 1 = 1 { AND c.name = ? } LIMIT ?d ', (empty($_POST['cat_name'])? DBSIMPLE_SKIP : 1), (empty($_POST['cat_name'])? DBSIMPLE_SKIP : $_POST['cat_name']), $pageSize );
列表 6:SQL 查询中的宏替换 #3
$rows = $DB->select(' SELECT * FROM user WHERE 1=0 { OR user_id IN(?a) } ', $listOfUserIdsMayBeEmpty // If empty, resulted to 1=0 which means false. );
列表 7:按时间缓存查询结果
$DB->setCacher('myCacher'); $row = $DB->select(' -- CACHE: 10h 20m 30s SELECT * FROM table WHERE id=123 '); // Define caching function. function myCacher($key, $value) { // If $value !== null then we must store it to the cache with key $key. // If $value === null then we must return the value stored in the cache with key $key. }
列表 8:基于表修改的查询结果缓存
// Here forum.modified and topic.modified are TIMESTAMPs. $row = $DB->select(' -- CACHE: 10h 20m 30s, forum.modified, topic.modified SELECT * FROM forum JOIN topic ON topic.forum_id=forum.id WHERE id=123 ');
列表 9:获取关联数组
$rows = $DB->select('SELECT user_id AS ARRAY_KEY, ?_user.* FROM ?_user'); foreach ($rows as $userId => $userData) { echo $userData['user_name']; }
列表 10:基于列表的占位符
$ids = array(1, 101, 303); $DB->select('SELECT name FROM tbl WHERE id IN(?a)', $ids); // SELECT name FROM tbl WHERE id IN(1, 101, 303)
列表 11:关联占位符
$row = array( 'id' => 10, 'date' => "2006-03-02" ); $DB->query('UPDATE tbl SET ?a', $row); // MySQL: UPDATE tbl SET `id`='10', `date`='2006-03-02'
列表 12:基于标识符的占位符
$DB->select('SELECT ?# FROM tbl', 'date'); // MySQL: SELECT `date` FROM tbl // FireBird: SELECT "date" FROM tbl
列表 13:基于标识符列表的占位符
$user = array('user_id' => 101, 'user_name' => 'Rabbit', 'user_age' => 30); $newUserId = $DB->query( 'INSERT INTO user(?#) VALUES(?a)', array_keys($row), array_values($row) );
列表 14:{基于前缀的占位符}
$DB->setIdentPrefix('phpbb_'); $DB->select('SELECT * FROM ?_user'); // SELECT * FROM phpbb_users
列表 15:单行获取
$row = $DB->selectRow('SELECT * FROM ?_user WHERE user_id=?', $uid);
列表 16:单单元格获取
$userName = $DB->selectCell( 'SELECT user_name FROM ?_user WHERE user_id=?', $uid );
列表 17:单列获取
$cities = $DB->selectCol('SELECT city_name FROM ?_cities'); $citiesById = $DB->selectCol( 'SELECT city_id AS ARRAY_KEY, city_name FROM ?_cities' );
列表 18:多维关联数组获取
$messagesByTopics = $DB->select(' SELECT message_topic_id AS ARRAY_KEY_1, message_id AS ARRAY_KEY_2, message_subject, message_text FROM ?_message '); // $messagesByForumsAndTopics[topicId][messageId] = messageData
列表 19:关联树获取
$forest = $DB->select(' SELECT person_id AS ARRAY_KEY, person_father_id AS PARENT_KEY, * FROM ?_person ');
列表 20:prepare ... execute 优化
foreach ($array as $item) { // DbSimple underatands that it should execure "prepare" only once! $DB->query('INSERT INTO tbl(field) VALUES(?)', $item); }
列表 21:错误处理
// File connect.php $DB = DbSimple_Generic::connect('mysql://test:test@localhost1/non-existed-db'); $DB->setErrorHandler('databaseErrorHandler'); function databaseErrorHandler($message, $info) { if (!error_reporting()) return; echo "SQL Error: $message<br><pre>"; print_r($info); echo "</pre>"; exit(); } // As a result we will get: SQL Error: Unknown MySQL Server Host 'localhost1' (11001) at .../connect.php line 17 Array ( [code] => 2005 [message] => Unknown MySQL Server Host 'localhost1' (11001) [query] => mysql_connect() [context] => .../connect.php line 17 )
列表 22:临时错误禁用
// Please note the "@" operator usage! // Also an unique index must be created for id field. if (!@$DB->query('INSERT INTO tbl(id, field) VALUES(1, ?)', $field)) { // Here goes the reaction on the query error. // You may fetch error context using $DB->error property. $DB->query('UPDATE tbl SET field=? WHERE id=1', $field); }
列表 23:查询日志
$DB->setLogger('myLogger'); $rows = $DB->select('SELECT * FROM U_GET_PARAM_LIST'); function myLogger($db, $sql) { $caller = $db->findLibraryCaller(); $tip = "at ".@$caller['file'].' line '.@$caller['line']; // Print the query (of course it's better to use Debug_HackerConsole). echo "<xmp title=\"$tip\">"; print_r($sql); echo "</xmp>"; } // Will be printed something like: SELECT * FROM U_GET_PARAM_LIST; --- 13 ms = 4+3+6; returned 30 row(s);