用PHP编写可重用的更新查询

时间:2017-05-05 15:51:13

标签: php mysql oop pdo

我试图基于Jeffery在laracast上的INSERT查询在PHP中编写可重用的UPDATE查询

这是Jeff的插入查询

public function insert($table, $parameters)
{
$sql = sprintf(
        'INSERT INTO %s (%s) VALUES (%s)',
        $table,
        implode(', ', array_keys($parameters)),
        ':' . implode(', :', array_keys($parameters))

    );
    try {
        $statement = $this->pdo->prepare($sql);
        $statement->execute($parameters);
    } catch (Exception $exception) {
        die("Something Went Wrong");
    }
}

这是我正在尝试编写的更新代码

public function update($table, $parameters, $Condition)
{
    $sql = sprintf(
        'UPDATE %s SET %s=%s WHERE ' . $Condition,
        $table,
        implode('=,', array_keys($parameters))
        ,
        ':' . implode(', :', array_keys($parameters))

    );


    try {
        $statement = $this->pdo->prepare($sql);
        $statement->execute($parameters);
    } catch (Exception $exception) {
        die("Something Went Wrong");
    }

}

我想通过传递

中的数据使其像Insert Query一样可重用

所有帮助都经过高度评价

2 个答案:

答案 0 :(得分:0)

这是非常糟糕的主意。不要这样做。

相反,我建议为您的实体创建自定义data mappers,其中包含手工制作的SQL,并使用正确绑定的参数/值。

但作为一项实验,我想出了这个:

public function update($table, $parameters, $conditions)
{
    $sql = sprintf(
        'UPDATE %s SET %s WHERE %s',
        $table,
        implode(', ',array_map(
            function ($key) {
                return "{$key} = :s_{$key}";
            },
            array_keys($parameters)
        )),
        implode(' AND ',array_map(
            function ($key) {
                return "{$key} = :w_{$key}";
            },
            array_keys($conditions)
        ))
    );

    $parameters = array_combine(
        array_map(function($key){ return ":s_{$key}"; }, array_keys($parameters)),
        $parameters
    ) + array_combine(
        array_map(function($key){ return ":w_{$key}"; }, array_keys($conditions)),
        $conditions
    );

    try {
        $statement = $this->pdo->prepare($sql);
        $statement->execute($parameters);
    } catch (Exception $exception) {
        die("Something Went Wrong");
    }

}

请记住,是您的用户"可能以某种方式影响$parameters$conditions数组的,然后此代码容易受到SQL注入攻击。

  

<强> P.S。
  在原始示例中,您将$Condition参数简单地连接到查询的末尾。这将造成SQL注入攻击的巨大风险。

答案 1 :(得分:0)

这是一种有效的[1]方法,可以从具有命名参数的字段名称数组生成UPDATE语句, 可以使用任意数据(例如,使用PDOStatements)执行。

[1]高效:它独家使用sprintf进行插值,无需级联。

适应症:

  • 您需要保留一些对象,而Doctrine之类的东西 过度杀伤
  • 您的对象不需要任何时髦的转换 保存之前对其数据进行处理
  • 用户将没有机会修改字段名称列表(在我的情况下,该字段已硬编码到PHP中)

我们都是成年人,可以在上述适应症适用时自行决定。

如果您有一个关联数组,那么只需先获取它的array_keys。

$tablename = 'character';
$fields = [
    'name',
    'class',
    'hitpoints',
    'battlecry'
];

$first = array_pop($fields);
$fmt = array_reduce($fields, function($carry, $item) {
    return sprintf($carry, sprintf(', %1$s = :%1$s %%s', $item));
}, sprintf(' SET %1$s = :%1$s %%s', $first));

$sql = sprintf('UPDATE %s %s ', $tablename, sprintf($fmt, ';'));

echo $fmt; // UPDATE character SET battlecry = :battlecry , name = :name , class = :class , hitpoints = :hitpoints ;