从PHP

时间:2016-03-31 13:39:03

标签: php arrays function pdo

我有一个看起来像这样的数组

$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);

是否可以在单一功能中实现这一目标?

3 个答案:

答案 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)

您可以通过创建QueryBuilderPDOStatementDecorator来实现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