tommyknocker/pdo-database-class

PHP PDO 包装器,利用 PDO 和预编译语句

1.1.1 2021-12-20 03:49 UTC

This package is auto-updated.

Last update: 2024-09-20 09:58:51 UTC


README

PHP PDO 包装器,利用 PDO 和预编译语句

目录

支持我

这款软件是在我的业余时间开发的,如果有人支持我,我将非常高兴。

每个人的时间都应该很有价值,所以请考虑捐赠。

使用 PayPal 捐赠

安装

要使用此类,请首先将 PDODb.php 导入到您的项目中,并要求它。PDODb 需要 PHP 5.5+ 才能工作。

require_once ('PDODb.php');

使用 composer 安装

还可以通过 composer 安装库

composer require tommyknocker/pdo-database-class

初始化

简单的初始化,默认设置 utf8 字符集

$db = new PDODb('host', 'username', 'password', 'databaseName');

高级初始化

$db = new PDODb(['type' => 'mysql',
                 'host' => 'host',
                 'username' => 'username', 
                 'password' => 'password',
                 'dbname'=> 'databaseName',
                 'port' => 3306,
                 'prefix' => 'my_',
                 'charset' => 'utf8']);

表前缀、端口号和数据库字符集参数是可选的。如果不设置字符集,则将其设置为 null

还可以重用已经连接的 PDO 对象

$pdo = new PDO('mysql:dbname=test;host=localhost', 'user', 'password');
$db = new PDODb($pdo);

如果在创建对象期间没有设置表前缀,可以在单独的调用中设置它

$db->setPrefix('my_');

如果您需要从另一个类或函数中获取已经创建的 PDO 对象,请使用

    function init() {
        // db staying private here
        $db = new PDODb('type', 'host', 'username', 'password', 'databaseName');
    }
    ...
    function myfunс() {
        // obtain db object created in init()
        $db = PDODb::getInstance();
        ...
    }

插入查询

简单示例

$data = ["login" => "admin",
         "firstName" => "John",
         "lastName" => 'Doe'
];
$id = $db->insert('users', $data);
if($id)
    echo 'user was created. Id=' . $id;

使用函数插入

$data = [
	'login' => 'admin',
    'active' => true,
	'firstName' => 'John',
	'lastName' => 'Doe',
	'password' => $db->func('SHA1(?)',Array ("secretpassword+salt")),
	// password = SHA1('secretpassword+salt')
	'createdAt' => $db->now(),
	// createdAt = NOW()
	'expires' => $db->now('+1Y')
	// expires = NOW() + interval 1 year
	// Supported intervals [s]econd, [m]inute, [h]hour, [d]day, [M]onth, [Y]ear
];

$id = $db->insert('users', $data);
if ($id) {
    echo 'user was created. Id=' . $id;
} else {
    echo 'insert failed: ' . $db->getLastError();
}

使用 ON DUPLICATE KEY UPDATE 插入

$data = ["login" => "admin",
         "firstName" => "John",
         "lastName" => 'Doe',
         "createdAt" => $db->now(),
         "updatedAt" => $db->now(),
];
$updateColumns = ["updatedAt"];
$lastInsertId = "id";
$db->onDuplicate($updateColumns, $lastInsertId);
$id = $db->insert('users', $data);

替换查询

Replace() 方法实现了与 insert() 相同的 API

更新查询

$data = ['firstName' => 'Bobby',
	    'lastName' => 'Tables',
	    'editCount' => $db->inc(2),
	    // editCount = editCount + 2;
	    'active' => $db->not()
	    // active = !active;
];
$db->where('id', 1);
if ($db->update('users', $data)) {
    echo $db->getRowCount() . ' records were updated';
} else {
    echo 'update failed: ' . $db->getLastError();
}

update() 也支持 limit 参数

$db->update('users', $data, 10);
// Gives: UPDATE users SET ... LIMIT 10

选择查询

在任何 select/get 函数调用之后,数量或返回的行数都存储在 $count 变量中

$users = $db->get('users'); //contains an Array of all users 
$users = $db->get('users', 10); //contains an Array 10 users

或选择自定义列。函数也可以使用

$cols = ["id", "name", "email"];
$users = $db->get("users", null, $cols);
if ($users) {
    foreach ($users as $user) { 
        print_r ($user);
    }
}

或只选择一行

$db->where("id", 1);
$user = $db->getOne("users");
echo $user['id'];

$stats = $db->getOne("users", "SUM(id), COUNT(*) as cnt");
echo "total ".$stats['cnt']. "users found";

或选择一个列值或函数结果

$count = $db->getValue("users", "COUNT(*)");
echo "{$count} users found";

从多行中选择一个列值或函数结果

$logins = $db->getValue("users", "login", null);
// select login from users
$logins = $db->getValue("users", "login", 5);
// select login from users limit 5
foreach ($logins as $login) {
    echo $login;
}

您可以使用 php 5.5+ 生成器功能与 PDODb get()、rawQuery() 方法一起使用,只需调用 useGenerator(true) 方法即可

示例

$result = $db->useGenerator(true)->get('users'); // $result will contain Generator object
if($result->current()) {
    foreach($result as $row) {
        print_r($row);
    }
}

分页

使用 paginate() 而不是 get() 来获取分页结果

$page = 1;
// set page limit to 2 results per page. 20 by default
$db->pageLimit = 2;
$products = $db->paginate("products", $page);
echo "showing $page out of " . $db->totalPages;

定义返回类型

要选择返回类型,请使用 setReturnType() 方法。

// Array return type
$= $db->getOne("users");
echo $u['login'];
// Object return type
$u = $db->setReturnType(PDO::FETCH_OBJ)->getOne("users");
echo $u->login;

运行原始 SQL 查询

$users = $db->rawQuery('SELECT * FROM users WHERE id >= ?', [10]);
foreach ($users as $user) {
    print_r($user);
}

$users = $db->rawQuery('SELECT * FROM users WHERE name=:name', ['name' => 'user1']);
foreach ($users as $user) {
    print_r($user);
}

为了避免长 if 检查,有一些辅助函数可以与原始查询选择结果一起使用

获取 1 行结果

$user = $db->rawQueryOne('SELECT * FROM users WHERE id=:id', [id => 10]);
echo $user['login'];
// Object return type
$user = $db->setReturnType(PDO::FETCH_OBJ)->rawQueryOne('SELECT * FROM users WHERE id=?', [10]);
echo $user->login;

获取 1 个列值作为字符串

$password = $db->rawQueryValue('SELECT password FROM users WHERE id=? LIMIT 1', [10]);
echo "Password is {$password}";
NOTE: for a rawQueryValue() to return string instead of an array 'limit 1' should be added to the end of the query.

获取多行中的 1 个列值

$logins = $db->rawQueryValue('SELECT login FROM users LIMIT 10');
foreach ($logins as $login) {
    echo $login;
}

更高级的示例

$params = [1, 'admin'];
$users = $db->rawQuery("SELECT id, firstName, lastName FROM users WHERE id = ? AND login = ?", $params);
print_r($users); // contains Array of returned rows

// will handle any SQL query
$params = [10, 1, 10, 11, 2, 10];
$query = "(
    SELECT a FROM t1
        WHERE a = ? AND B = ?
        ORDER BY a LIMIT ?
) UNION (
    SELECT a FROM t2 
        WHERE a = ? AND B = ?
        ORDER BY a LIMIT ?
)";
$result = $db->rawQuery($query, $params);
print_r ($result); // contains array of returned rows

WHERE / HAVING 方法

where()orWhere()having()orHaving() 方法允许您指定查询的 WHERE 和 HAVING 条件。where() 支持的所有条件都由 having() 支持。

警告:为了使用列与列的比较,只能使用原始 WHERE 条件作为列名或不能将函数作为绑定变量传递。

带有变量的常规 == 运算符

$db->where('id', 1);
$db->where('login', 'admin');
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE id=1 AND login='admin';
$db->where ('id', 1);
$db->having ('login', 'admin');
$results = $db->get ('users');
// Gives: SELECT * FROM users WHERE id=1 HAVING login='admin';

列与列之间比较的常规 == 运算符

// WRONG
$db->where('lastLogin', 'createdAt');
// CORRECT
$db->where('lastLogin = createdAt');
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE lastLogin = createdAt;
$db->where('id', 50, ">=");
// or $db->where('id', ['>=' => 50]);
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE id >= 50;

BETWEEN / NOT BETWEEN

$db->where('id', [4, 20], 'BETWEEN');

$results = $db->get('users');
// Gives: SELECT * FROM users WHERE id BETWEEN 4 AND 20

IN / NOT IN

$db->where('id', [1, 5, 27, -1, 'd'], 'IN');
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE id IN (1, 5, 27, -1, 'd');

OR CASE

$db->where('firstName', 'John');
$db->orWhere('firstName', 'Peter');
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE firstName='John' OR firstName='peter'
$db->where('firstName', 'John');
$db->orWhere('firstName', 'Peter');
$results = $db->get('users');
// Gives: SELECT * FROM users WHERE firstName='John' OR firstName='peter'

NULL 比较

$db->where("lastName", NULL, 'IS NOT');
$results = $db->get("users");
// Gives: SELECT * FROM users where lastName IS NOT NULL

您还可以使用原始 WHERE 条件

$db->where("id != companyId");
$db->where("DATE(createdAt) = DATE(lastLogin)");
$results = $db->get("users");

或带有变量的原始条件

$db->where("(id = ? OR id = ?)", [6,2]);
$db->where("login","mike")
$res = $db->get ("users");
// Gives: SELECT * FROM users WHERE (id = 6 OR id = 2) AND login='mike';

查找匹配的总行数。简单的分页示例

$offset = 10;
$count = 15;
$users = $db->withTotalCount()->get('users', [$offset, $count]);
echo "Showing {$count} from {$db->totalCount}";

查询关键字

可以将 LOW PRIORITY | DELAYED | HIGH PRIORITY | IGNORE 以及其余的 mysql 关键字添加到 INSERT ()、REPLACE ()、GET ()、UPDATE ()、DELETE() 方法或 FOR UPDATE | LOCK IN SHARE MODE 中 SELECT ()

$db->setQueryOption('LOW_PRIORITY')->insert($table, $param);
// GIVES: INSERT LOW_PRIORITY INTO table ...
$db->setQueryOption('FOR UPDATE')->get('users');
// GIVES: SELECT * FROM USERS FOR UPDATE;

您还可以使用关键字数组

$db->setQueryOption(['LOW_PRIORITY', 'IGNORE'])->insert($table,$param);
// GIVES: INSERT LOW_PRIORITY IGNORE INTO table ...

同样,关键字也可以用在 SELECT 查询中

$db->setQueryOption('SQL_NO_CACHE');
$db->get("users");
// GIVES: SELECT SQL_NO_CACHE * FROM USERS;

可选地,您可以使用方法链来多次调用 where 而不重复引用您的对象

$results = $db
	->where('id', 1)
	->where('login', 'admin')
	->get('users');

删除查询

$db->where('id', 1);
if($db->delete('users')) echo 'successfully deleted';

排序方法

$db->orderBy("id","ASC");
$db->orderBy("login","DESC");
$db->orderBy("RAND ()");
$results = $db->get('users');
// Gives: SELECT * FROM users ORDER BY id ASC,login DESC, RAND ();

按值排序示例

$db->orderBy('userGroup', 'ASC', ['superuser', 'admin', 'users']);
$db->get('users');
// Gives: SELECT * FROM users ORDER BY FIELD (userGroup, 'superuser', 'admin', 'users') ASC;

如果您使用 setPrefix () 功能并且需要在 orderBy() 方法中使用表名,请确保表名被反引号 `` 包围。

$db->setPrefix("t_");
$db->orderBy("users.id","ASC");
$results = $db->get('users');
// WRONG: That will give: SELECT * FROM t_users ORDER BY users.id ASC;

$db->setPrefix("t_");
$db->orderBy("`users`.id", "ASC");
$results = $db->get('users');
// CORRECT: That will give: SELECT * FROM t_users ORDER BY t_users.id ASC;

分组方法

$db->groupBy("name");
$results = $db->get('users');
// Gives: SELECT * FROM users GROUP BY name;

通过 tenantID 使用 LEFT JOIN 将产品表与用户表连接

JOIN 方法

$db->join("users u", "p.tenantID=u.tenantID", "LEFT");
$db->where("u.id", 6);
$products = $db->get("products p", null, "u.name, p.productName");
print_r($products);

属性共享

也可以复制属性

$db->where("agentId", 10);
$db->where("active", true);

$customers = $db->copy();
$res = $customers->get("customers", [10, 10]);
// SELECT * FROM customers where agentId = 10 and active = 1 limit 10, 10

$cnt = $db->getValue("customers", "COUNT(id)");
echo "total records found: " . $cnt;
// SELECT COUNT(id) FROM users WHERE agentId = 10 AND active = 1

子查询

子查询初始化

子查询初始化,不带别名用于插入/更新/where。例如:(select * from users)

$sq = $db->subQuery();
$sq->get("users");

指定别名的子查询,用于 JOIN。例如:(select * from users) sq

$sq = $db->subQuery("sq");
$sq->get("users");

子查询在 SELECT 中的使用

$ids = $db->subQuery ();
$ids->where("qty", 2, ">");
$ids->get("products", null, "userId");

$db->where("id", $ids, 'in');
$res = $db->get("users");
// Gives SELECT * FROM users WHERE id IN (SELECT userId FROM products WHERE qty > 2)

子查询在 INSERT 中的使用

$userIdQ = $db->subQuery ();
$userIdQ->where("id", 6);
$userIdQ->getOne("users", "name");

$data = ["productName" => "test product",
         "userId" => $userIdQ,
         "lastUpdated" => $db->now()
];
$id = $db->insert("products", $data);
// Gives INSERT INTO PRODUCTS (productName, userId, lastUpdated) values ("test product", (SELECT name FROM users WHERE id = 6), NOW());

子查询在 JOIN 中的使用

$usersQ = $db->subQuery("u");
$usersQ->where("active", 1);
$usersQ->get("users");

$db->join($usersQ, "p.userId=u.id", "LEFT");
$products = $db->get("products p", null, "u.login, p.productName");
print_r($products);
// SELECT u.login, p.productName FROM products p LEFT JOIN (SELECT * FROM t_users WHERE active = 1) u on p.userId=u.id;

EXISTS / NOT EXISTS 条件

$sub = $db->subQuery();
$sub->where("company", 'testCompany');
$sub->get ("users", null, 'userId');
$db->where (null, $sub, 'EXISTS');
$products = $db->get ("products");
// Gives SELECT * FROM products WHERE EXISTS (select userId from users where company='testCompany')

has 方法

一个方便的函数,如果存在至少一个满足之前调用 "where" 方法的 where 条件的元素,则返回 TRUE。

$db->where("user", $user);
$db->where("password", md5($password));
if($db->has("users")) {
    return "You are logged";
} else {
    return "Wrong user/password";
}

辅助方法

获取最后执行的 SQL 查询:请注意,此函数仅用于调试目的,因为它返回的 SQL 查询由于缺少字符变量的引号而可能无法执行。

$db->get('users');
echo "Last executed query was ". $db->getLastQuery();

检查表是否存在

if ($db->tableExists('users')) {
    echo "hooray";
}

pdo::quote() 包装器

$escaped = $db->escape("' and 1=1");

事务辅助函数

请注意,事务是在 innoDB 表上运行的。如果插入失败,则回滚事务

$db->startTransaction();
...
if (!$db->insert('myTable', $insertData)) {
    //Error while saving, cancel new record
    $db->rollback();
} else {
    //OK
    $db->commit();
}

错误辅助函数

在执行查询后,您可以选择检查是否发生错误。您可以获取最后一个执行的查询的 MySQL 错误字符串或错误代码。

$db->where('login', 'admin')->update('users', ['firstName' => 'Jack']);

if ($db->getLastErrNo() === 0) {
    echo 'Update succesfull';
} else {
    echo 'Update failed. Error: '. $db->getLastError();
}