هل البيانات الديناميكية المعدة سيئة؟(باستخدام PHP + Mysqli)

StackOverflow https://stackoverflow.com/questions/201468

سؤال

تعجبني مرونة Dynamic SQL وأحب الأمان + الأداء المحسن للبيانات المعدة.لذا فإن ما أريده حقًا هو البيانات الديناميكية المعدة، وهو أمر يصعب إجراؤه لأن bind_param وbind_result يقبلان عددًا "ثابتًا" من الوسائط.لذلك استفدت من عبارة eval() للتغلب على هذه المشكلة.لكني أشعر أن هذه فكرة سيئة.فيما يلي رمز المثال لما أعنيه

// array of WHERE conditions
$param = array('customer_id'=>1, 'qty'=>'2');
$stmt = $mysqli->stmt_init();

$types = ''; $bindParam = array(); $where = ''; $count = 0;

// build the dynamic sql and param bind conditions
foreach($param as $key=>$val)
{
    $types .= 'i';
    $bindParam[] = '$p'.$count.'=$param["'.$key.'"]'; 
    $where .= "$key = ? AND ";
    $count++;
}

// prepare the query -- SELECT * FROM t1 WHERE customer_id = ? AND qty = ?
$sql = "SELECT * FROM t1 WHERE ".substr($where, 0, strlen($where)-4);
$stmt->prepare($sql);

// assemble the bind_param command
$command = '$stmt->bind_param($types, '.implode(', ', $bindParam).');';

// evaluate the command -- $stmt->bind_param($types,$p0=$param["customer_id"],$p1=$param["qty"]);
eval($command);

هل بيان eval() الأخير فكرة سيئة؟لقد حاولت تجنب إدخال التعليمات البرمجية عن طريق تغليف القيم خلف اسم المتغير $param.

هل لدى أي شخص رأي أو اقتراحات أخرى؟هل هناك مشكلات يجب أن أكون على دراية بها؟

هل كانت مفيدة؟

المحلول

أعتقد أنه خطير للاستخدام eval() هنا.

جرب هذا:

  • قم بتكرار مجموعة المعلمات لإنشاء سلسلة SQL مع علامات الاستفهام "SELECT * FROM t1 WHERE p1 = ? AND p2 = ?"
  • يتصل prepare() على ذلك
  • يستخدم call_user_func_array() لإجراء المكالمة إلى bind_param(), ، مروراً بمصفوفة المعلمات الديناميكية.

الرمز:

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

نصائح أخرى

ولقد تقدمت وظيفة مرشح الذي recives مجموعة مجموعة asociative مثل $ _GET:

في الدرجة نموذج قمت بتحديدها لي اثنين من الخصائص بما في ذلك المخطط:

private $table_name = "products";

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

وبعد ذلك طريقة المرشح الذي الجليل والمصفوفات asociative من الشروط:

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

ويعمل كبيرة لتصفية النتائج

وأنت لا حقا بحاجة البيانات المعدة والحجج ملزمة، لأنه يمكنك دائما استخدام mysql_real_escape_string (). وكنت على حق. SQL ديناميكيا هو أكثر بكثير مرونة وقيمة.

وإليك مثال بسيط باستخدام العادية mysql_ * واجهة:

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

وبطبيعة الحال، هذا هو مثال مبسط، وجعلها مفيدة لديكم لبناء وصقل ذلك كثيرا، لكنه يظهر الأفكار وانها حقا جدا مفيد للغاية. على سبيل المثال، وهنا هو وظيفة عامة تماما لإدراج صف جديد في جدول التعسفي، مع الأعمدة مليئة القيم من وضع مجموعة النقابي وبشكل كامل حقن SQL آمنة:

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));
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top