仅使用 PDO 是不可能的。您必须创建一个查询构建器类(或使用现有的众多类之一)包装 PDO,它将保存所有查询的属性,并一次构建完整的查询就在你执行它之前。
这是一个如何工作的基本示例:
class Query {
private $select;
private $from;
private $where = [];
/**
* Defines the column list (SELECT {$columns})
*
* @param string $columns
* @return this
*/
public function select($columns) {
$this->select = $columns;
return $this;
}
/**
* Defines the table to select from (SELECT * FROM {$table})
*
* @param string $table
* @return this
*/
public function from($table) {
$this->from = $table;
return $this;
}
/**
* List of conditions to AND (key = column, value = value)
* e.g. $query->where(['name' => 'bob'])
*
* @param mixed[string] $conditions
* @return $this
*/
public function where(array $conditions) {
$this->where = $conditions;
return $this;
}
/**
* Adds an AND condition
*
* @param string $column
* @param mixed $value
* @return this
*/
public function where_and($column, $value) {
$this->where[$column] = $value;
return $this;
}
/**
* Builds and executes the query, returning a PDOStatement
*
* @return PDOStatement
*/
public function execute() {
$query = sprintf(
'SELECT %s FROM %s',
$this->select,
$this->from
);
$placeholders = array();
if (!empty($this->where)) {
$query .= ' WHERE ';
$index = 0;
foreach ($this->where as $column => $value) {
if ($index > 0) {
$query .= ' AND ';
}
$query .= sprintf('`%s`', $column);
if ($value === null) {
$query .= ' IS NULL';
} else {
$placeholder = sprintf(':placeholder_%d', $index);
$query .= ' = ' . $placeholder;
$placeholders[$placeholder] = $value;
}
$index++;
}
}
$pdo = new PDO($dsn, $user, $pass, $opt);
$stmt = $pdo->prepare($query);
$stmt->execute($placeholders);
return $stmt;
}
}
例如,通过这个类,您可以执行以下操作:
class MyClass {
public function getData($name, $club) {
$query = new Query();
$query->select('name')
->from('users')
->where(['quote' => '1']);
$this->getQueryPart($query);
$result = $query->execute();
return $result->fetchAll(PDO::FETCH_ASSOC);
}
protected function getQueryPart($query) {
$query->where_and('email', 'email@foobar.com')
->where_and('status', 1);
}
}
查看此处的示例,该示例实际上并未执行查询,但会打印将执行的查询和占位符:https://3v4l.org/iKu2K
请注意,这是一个非常基本的示例,只是为了让您了解如何进行此类操作。在现实世界的场景中,您可能希望通过OR-conditions 以及LIKE 和!= 检查的功能来扩展它,甚至可能对条件进行分组,以便您可以执行WHERE a = 1 AND (b = 2 OR c = 5) 之类的操作。更不用说添加对JOIN、ORDER BY、LIMIT 和其他花哨的东西的支持了。