gpt4 book ai didi

php - 简单的 PDO 包装器

转载 作者:IT王子 更新时间:2023-10-29 00:21:14 26 4
gpt4 key购买 nike

我的 web 应用程序目前执行简单的查询:简单的 CRUD 操作、计数、...

几个月前,有人在这里推荐我为此编写一个简单的 PDO 包装器(以避免每次执行查询时都编写 try/catch、prepare()、execute() 等)。显示了此示例方法(我做了一些更改,以便可以在我自己的项目中使用它):

public function execute() {
$args = func_get_args();
$query = array_shift($args);
$result = false;

try {
$res = $this->pdo->prepare($query);
$result = $res->execute($args);
} catch (PDOException $e) { echo $e->getMessage(); }

return $result;
}

因为我需要执行更多操作(执行查询、检索 1 条记录、检索多条记录、计算结果),我为所有这些创建了一个方法:

  public function getMultipleRecords() {
$args = func_get_args();
$query = array_shift($args);
$records = array();

try {
$res = $this->pdo->prepare($query);
$res->execute($args);
$records = $res->fetchAll();
} catch (PDOException $e) { echo $e->getMessage(); }

return $records;
}

public function getSingleRecord() {
$args = func_get_args();
$query = array_shift($args);
$record = array();

try {
$res = $this->pdo->prepare($query);
$res->execute($args);
$record = $res->fetch();
} catch (PDOException $e) { echo $e->getMessage(); }

return $record;
}

public function execute() {
$args = func_get_args();
$query = array_shift($args);
$result = false;

try {
$res = $this->pdo->prepare($query);
$result = $res->execute($args);
} catch (PDOException $e) { echo $e->getMessage(); }

return $result;
}

public function count() {
$args = func_get_args();
$query = array_shift($args);
$result = -1;

try {
$res = $this->pdo->prepare($query);
$res->execute($args);
$result = $res->fetchColumn();
} catch(PDOException $e) { echo $e->getMessage(); }

return $result;
}

如您所见,大部分代码都是相同的。每种方法只有两行代码不同:$result 的初始化(我总是想返回一个值,即使查询失败)和获取。我可以不使用 4 种方法,而是只编写其中一种方法并传递一个带有操作类型的额外参数。这样,我就可以使用 switch 语句的一堆 if/else 语句。但是,我认为代码可能会变得困惑。这是解决这个问题的好方法吗?如果不是,有什么好的解决方案?

我遇到的第二个问题(这就是我现在正在研究此类的原因)是我想将准备好的语句与 LIMIT SQL 语句一起使用。但是,这是不可能的:

$res = $pdo->prepare("SELECT * FROM table LIMIT ?");
$res->execute(array($int));

变量将出于某种原因被引用(因此查询将失败),如下所述: https://bugs.php.net/bug.php?id=40740

该解决方案似乎使用 bindValue() 并将 int 数据类型用作参数: http://www.php.net/manual/de/pdostatement.bindvalue.php

我可以重写方法来支持这一点,但我还需要使用一个额外的参数。我不能再使用 $db->e​​xecute($sql, $variable1, $variable2); 因为我需要知道数据类型。

解决这个问题的最佳方法是什么?

谢谢

最佳答案

如何使用可以链接的方法创建一个类(为清楚起见,我删除了错误检查):

class DB {

private $dbh;
private $stmt;

public function __construct($user, $pass, $dbname) {
$this->dbh = new PDO(
"mysql:host=localhost;dbname=$dbname",
$user,
$pass,
array( PDO::ATTR_PERSISTENT => true )
);
}

public function query($query) {
$this->stmt = $this->dbh->prepare($query);
return $this;
}

public function bind($pos, $value, $type = null) {

if( is_null($type) ) {
switch( true ) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}

$this->stmt->bindValue($pos, $value, $type);
return $this;
}

public function execute() {
return $this->stmt->execute();
}

public function resultset() {
$this->execute();
return $this->stmt->fetchAll();
}

public function single() {
$this->execute();
return $this->stmt->fetch();
}
}

然后你可以像这样使用它:

// Establish a connection.
$db = new DB('user', 'password', 'database');

// Create query, bind values and return a single row.
$row = $db->query('SELECT col1, col2, col3 FROM mytable WHERE id > ? LIMIT ?')
->bind(1, 2)
->bind(2, 1)
->single();

// Update the LIMIT and get a resultset.
$db->bind(2,2);
$rs = $db->resultset();

// Create a new query, bind values and return a resultset.
$rs = $db->query('SELECT col1, col2, col3 FROM mytable WHERE col2 = ?')
->bind(1, 'abc')
->resultset();

// Update WHERE clause and return a resultset.
$db->bind(1, 'def');
$rs = $db->resultset();

如果您愿意,您可以更改 bind 方法以接受数组或关联数组,但我发现这种语法非常清晰 - 它避免了必须构建数组。参数类型检查是可选的,因为 PDO::PARAM_STR 适用于大多数值,但要注意传递空值时的潜在问题(请参阅 comment in PDOStatement->bindValue 文档)。

关于php - 简单的 PDO 包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6740153/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com