Are Dynamic Prepared Statements Bad? (with php + mysqli)

江枫思渺然 提交于 2019-11-28 07:04:29
Tomalak

I think it is dangerous to use eval() here.

Try this:

  • iterate the params array to build the SQL string with question marks "SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • call prepare() on that
  • use call_user_func_array() to make the call to bind_param(), passing in the dynamic params array.

The code:

call_user_func_array(array($stmt, 'bind_param'), array($types)+$param);

I made a filter function which recives an array an asociative array like $_GET:

In model class I've defined a couple of properties including the schema:

private $table_name = "products";

protected $schema = [
    'id' => 'INT',
    'name' => 'STR',
    'description' => 'STR',
    'size' => 'STR',
    'cost' => 'INT',
    'active' => 'BOOL'
];

Then a filter method which recive an asociative arrays of conditions:

function filter($conditions)
{
    $vars   = array_keys($conditions);
    $values = array_values($conditions);

    $where = '';
    foreach($vars as $ix => $var){
        $where .= "$var = :$var AND ";
    }
    $where =trim(substr($where, 0, strrpos( $where, 'AND ')));

    $q  = "SELECT * FROM {$this->table_name} WHERE $where";
    $st = $this->conn->prepare($q);

    foreach($values as $ix => $val){
        $st->bindValue(":{$vars[$ix]}", $val, constant("PDO::PARAM_{$this->schema[$vars[$ix]]}"));
    }

    $st->execute();
    return $st->fetchAll(PDO::FETCH_ASSOC);
}

And works great to filter results

You don't really need prepared statements and bound arguments, because you can always use mysql_real_escape_string(). And you're right; dynamically generated SQL is far more flexible and valuable.

Here's a simple example using the regular mysql_* interface:

// Array of WHERE conditions
$conds = array("customer_id" => 1, "qty" => 2);

$wherec = array("1");
foreach ($conds as $col=>$val) $wherec[] = sprintf("`%s` = '%s'", $col, mysql_real_escape_string($val));

$result_set = mysql_query("SELECT * FROM t1 WHERE " . implode(" AND ", $wherec);

Of course, this is a simplistic example, and to make it useful you have to build and refine it a lot, but it shows the ideas and it's really very very useful. For example, here is a completely generic function to insert a new row into an arbitrary table, with the columns filled with the values from an associative array and completely SQL-injection safe:

function insert($table, $record) {
    $cols = array();
    $vals = array();
    foreach (array_keys($record) as $col) $cols[] = sprintf("`%s`", $col);
    foreach (array_values($record) as $val) $vals[] = sprintf("'%s'", mysql_real_escape_string($val));

    mysql_query(sprintf("INSERT INTO `%s`(%s) VALUES(%s)", $table, implode(", ", $cols), implode(", ", $vals)));
}

// Use as follows:
insert("customer", array("customer_id" => 15, "qty" => 86));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!