我有一个看起来像这样的数组
$users = array(
array('name'=>'aaa','age'=>2),
array('name'=>'bbb','age'=>9),
array('name'=>'ccc','age'=>7)
);
我想创建一个接受上面数组的函数,为单个查询多次插入创建一个子句,准备一个可以与PDO绑定的变量数组。
示例输出:
$clause = INSERT INTO tablename (`name`,`age`)
VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
然后是另一组与上述值对应的数组:
$params => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
);
这样就可以像这样执行它:
$prepared = $connection->prepare($clause);
$prepared->execute($params);
是否可以在单一功能中实现这一目标?
答案 0 :(得分:2)
是的,非常可能,我为自定义查询构建器类做了完全相同的事情:
function INSERT_MULTIPLE_QUERY($ARRS = array()){
$raw_cols = '(`';
// PREPARE THE COLUMNS
foreach($ARRS[0] as $key1 => $value):
$raw_cols .= $key1.'`,`';
endforeach;
$final_cols = rtrim($raw_cols,'`,`') . '`)';
$ctr1=0; $raw_vals='';
// PREPARE THE VALUES
foreach($ARRS as $ARR_VALUE):
$raw_vals .= '(';
foreach($ARR_VALUE as $key => $value): $raw_vals .= ':'.$key.'_'.$ctr1.','; endforeach;
$raw_vals = rtrim($raw_vals,',');
$raw_vals .= '),';
$ctr1++;
endforeach;
$final_vals = rtrim($raw_vals,',');
$ctr2 = 0; $param = array();
// PREPARE THE PARAMETERS
foreach($ARRS as $ARR_PARAM):
foreach($ARR_PARAM as $key_param => $value_param):$param[$key_param.'_'.$ctr2] = $value_param; endforeach;
$ctr2++;
endforeach;
// PREPARE THE CLAUSE
$clause = 'INSERT INTO tablename ' . $final_cols . ' VALUES ' . $final_vals;
// RETURN THE CLAUSE AND THE PARAMETERS
$return['clause'] = $clause;
$return['param'] = $param;
return $return;
}
现在使用此功能:
$query = INSERT_MULTIPLE_QUERY($users);
// $users is your example array above
然后:
$prepared = $connection->prepare($query['clause']);
$prepared->execute($query['param']);
答案 1 :(得分:0)
您可以通过创建QueryBuilder
和PDOStatementDecorator
来实现OOP风格:
class QueryBuilder
{
const BUILD_TYPE_INSERT_MULTIPLE = 'INSERT_MULTIPLE';
protected $table;
protected $values;
protected $buildType;
public function __construct($table)
{
$this->table = $table;
}
public static function onTable($table)
{
return new self($table);
}
public function insertMultiple(Array $values = array())
{
$this->values = $values;
$this->buildType = self::BUILD_TYPE_INSERT_MULTIPLE;
return $this;
}
public function build()
{
switch ($this->buildType) {
case self::BUILD_TYPE_INSERT_MULTIPLE:
return $this->buildInsertMultiple();
}
}
protected function buildInsertMultiple()
{
$fields = array_keys($this->values[0]);
$query = "INSERT INTO {$this->table} (" . implode(',', $fields) . ") VALUES ";
$values = array();
for ($i = 0; $i < count($fields); $i++) {
$values[] = '(' . implode(', ', array_map(function($field) use ($i) {
return ':' . $field . $i;
}, $fields)) . ')';
}
$query .= implode(', ', $values);
return $query;
}
}
class PDOStatementDecorator
{
protected $pdoStatement;
public function __construct(PDOStatement $pdoStatement)
{
$this->pdoStatement = $pdoStatement;
}
public function executeMultiple(Array $bindsGroup = array())
{
$binds = array();
for ($i = 0; $i < count($bindsGroup); $i++) {
foreach ($bindsGroup[$i] as $key => $value) {
$binds[$key . $i] = $value;
}
}
return $this->execute($binds);
}
public function execute(Array $inputParemeters)
{
return $this->pdoStatement->execute($inputParemeters);
}
public function fetch($fetchStyle = null, $cursorOrientation = 'PDO::FETCH_ORI_NEXT', $cursorOffset = 0)
{
return $this->pdoStatement->fetch($fetchStyle, $cursorOrientation, $cursorOffset);
}
/**
* TODO
* Implement all public PDOStatement methods
*/
}
可以增强查询构建器,以便能够为更新/删除语句构建查询。
现在使用非常简单:
$users = array(
array('name' => 'aaa', 'age' => 2),
array('name' => 'bbb', 'age' => 9),
array('name' => 'ccc', 'age' => 7),
);
$query = QueryBuilder::onTable('users')->insertMultiple($users)->build();
$stmt = new PDOStatementDecorator($pdo->prepare($query));
$stmt->executeMultiple($users);
答案 2 :(得分:0)
只有当所有数组行中都不存在一个字段时,此函数才需要表名,原始数组和用作默认值的可选参数:
function buildQuery( $table, $array, $default='NULL' )
{
/* Retrieve complete field names list: */
$fields = array();
foreach( $array as $row ) $fields = array_merge( $fields, array_keys( $row ) );
$fields = array_unique( $fields );
/* Analize each array row, then update parameters and values chunks: */
$values = $params = array();
foreach( $array as $key => $row )
{
$line = array();
foreach( $fields as $field )
{
if( !isset( $row[$field] ) )
{ $line[] = $default; }
else
{
$line[] = ":{$field}_{$key}";
$params["{$field}_{$key}"] = $row[$field];
}
}
$values[] = '('.implode(',',$line).')';
}
/* Compone MySQL query: */
$clause = sprintf
(
"INSERT INTO `%s` (`%s`) VALUES %s;",
$table,
implode( '`,`', $fields ),
implode( ',', $values )
);
/* Return array[ clause, params ]: */
return compact( 'clause', 'params' );
}
以这种方式调用它:
$query = buildQuery( 'mytable', $users );
$query
将包含此内容:
Array
(
[clause] => INSERT INTO `mytable` (`name`,`age`) VALUES (:name_0,:age_0),(:name_1,:age_1),(:name_2,:age_2);
[params] => Array
(
[name_0] => aaa
[age_0] => 2
[name_1] => bbb
[age_1] => 9
[name_2] => ccc
[age_2] => 7
)
)
的 eval.in demo 强>