9

私はこのような配列を持っています

  $a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );

var-dumpを実行すると、これが表示されます->

 { ["phone"]=> int(111111111) ["image"]=> string(19) "sadasdasd43eadasdad" }

今私はINステートメントを使用してこれをDBに追加しようとしています-

 $q = $DBH->prepare("INSERT INTO user :column_string VALUES :value_string");
 $q->bindParam(':column_string',implode(',',array_keys($a)));
 $q->bindParam(':value_string',implode(',',array_values($a)));
 $q->execute();

私が抱えている問題は、爆縮が文字列を返すことです。ただし、「phone」列はデータベース内の整数であり、配列はそれを整数として格納しています。したがって、最終的なクエリは次のようになり、SQLエラーが発生します-

INSERT INTO user 'phone,image' values '111111111,sadasdasd43eadasdad';

これは間違ったクエリです。それを回避する方法はありますか?

私の列名は、ユーザーが挿入したいものに基づいて動的になっています。したがって、:phone:imageのようなプレースホルダーを使用することはできません。これらの2つの列の値を常に取得できるとは限らないためです。これを回避する方法があれば教えてください。それ以外の場合は、更新の種類ごとに複数の関数を定義する必要があります。

ありがとう。

4

7 に答える 7

10

前回チェックしたとき、影響を受ける列が準備時に不明であるステートメントを準備することはできませんでしたが、それは機能しているようです。おそらく、データベースシステムは私が使用しているものよりも寛容です(主にpostgres)

明らかに間違っているのは、implode()ステートメントです。各変数はそれ自体で処理する必要があるため、insertステートメントのフィールドリストを括弧で囲む必要もあります。

ユーザー定義のフィールドを挿入するには、次のようなことをする必要があると思います(少なくとも私が行う方法)。

$fields=array_keys($a); // here you have to trust your field names! 
$values=array_values($a);
$fieldlist=implode(',',$fields); 
$qs=str_repeat("?,",count($fields)-1);
$sql="insert into user($fieldlist) values(${qs}?)";
$q=$DBH->prepare($sql);
$q->execute($values);

$ aのフィールド名を信頼できない場合は、次のようなことを行う必要があります。

foreach($a as $f=>$v){
   if(validfield($f)){
      $fields[]=$f;
      $values[]=$v;
   }
}

ここで、validfieldsは、各フィールド名をテストし、それが有効かどうかをチェックする、作成した関数です(連想配列$ valfields = array('name' => 1、'email' => 1、'phone' = > 1 ...次に、$ valfields [$ f]の値をチェックするか、(私が好むように)サーバーからフィールド名をフェッチして)

于 2012-11-22T07:51:55.920 に答える
6

SQLクエリパラメータは、リテラル値を入力する場合にのみ使用できます。

したがって、引用符で囲まれた文字列リテラル、日付リテラル、または数値リテラルをクエリのその位置に配置していることがわかる場合は、パラメータを使用できます。

列名、テーブル名、値の一覧、SQLキーワード、またはその他の式や構文にパラメーターを使用することはできません。

そのような場合でも、コンテンツをSQL文字列に補間する必要があるため、SQLインジェクションのリスクがあります。これを防ぐ方法は、列名をホワイトリストに登録し、ホワイトリストに一致しない入力を拒否することです。

于 2012-11-22T08:06:06.360 に答える
4

他のすべての回答ではSQLインジェクションが許可されているためです。ユーザー入力の場合、許可されたフィールド名をフィルタリングする必要があります。

// change this
$fields = array('email', 'name', 'whatever');
$fieldlist = implode(',', $fields);
$values = array_values(array_intersect_key($_POST, array_flip($fields)));
$qs = str_repeat("?,",count($fields)-1) . '?';
$q = $db->prepare("INSERT INTO events ($fieldlist) values($qs)");
$q->execute($values);
于 2016-06-02T12:11:00.543 に答える
3

MortenSickelの答えに感謝しましたが、安全のために名前付きパラメーターを使用したいと思いました。

    $keys = array_keys($a);
    $sql = "INSERT INTO user (".implode(", ",$keys).") \n";
    $sql .= "VALUES ( :".implode(", :",$keys).")";        
    $q = $this->dbConnection->prepare($sql);
    return $q->execute($a);
于 2015-05-21T22:58:31.530 に答える
2

実際には、事前に:phoneand:imageフィールドをnull値でバインドすることができます。テーブルの構造はとにかく固定されており、おそらくそのようにする必要があります。


しかし、あなたの質問に対する答えは次のようになります。

$keys = ':' . implode(', :', array_keys($array)); 
$values = str_repeat('?, ', count($array)-1) . '?';

$i = 1;
$q = $DBH->prepare("INSERT INTO user ($keys) VALUES ($values)");

foreach($array as $value)
    $q->bindParam($i++, $value, PDO::PARAM_STR, mb_strlen($value));
于 2012-11-22T08:45:44.200 に答える
2

私はこの質問がずっと前に答え​​られたことを知っています、しかし私は今日それを見つけて、@MortenSickelの答えに加えて少し貢献しています。

以下のクラスでは、データベーステーブルに連想配列を挿入または更新できます。MySQL PDOの詳細については、http://php.net/manual/en/book.pdo.phpにアクセスしてください。

<?php

class dbConnection
{
  protected $dbConnection;

  function __construct($dbSettings) {
    $this->openDatabase($dbSettings);
  }

  function openDatabase($dbSettings) {  
    $dsn = 'mysql:host='.$dbSettings['host'].';dbname='.$dbSettings['name'];
    $this->dbConnection = new PDO($dsn, $dbSettings['username'], $dbSettings['password']);
    $this->dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  }

  function insertArray($table, $array) {
    $fields=array_keys($array);
    $values=array_values($array);
    $fieldlist=implode(',', $fields); 
    $qs=str_repeat("?,",count($fields)-1);

    $sql="INSERT INTO `".$table."` (".$fieldlist.") VALUES (${qs}?)";

    $q = $this->dbConnection->prepare($sql);
    return $q->execute($values);
  }

  function updateArray($table, $id, $array) {
    $fields=array_keys($array);
    $values=array_values($array);
    $fieldlist=implode(',', $fields); 
    $qs=str_repeat("?,",count($fields)-1);
    $firstfield = true;

    $sql = "UPDATE `".$table."` SET";
    for ($i = 0; $i < count($fields); $i++) {
        if(!$firstfield) {
        $sql .= ", ";   
        }
        $sql .= " ".$fields[$i]."=?";
        $firstfield = false;
    }
    $sql .= " WHERE `id` =?";

    $sth = $this->dbConnection->prepare($sql);
    $values[] = $id;
    return $sth->execute($values);
  }
}
?>

dbConnectionクラスの使用法:

<?php
  $dbSettings['host'] = 'localhost';
  $dbSettings['name'] = 'databasename';
  $dbSettings['username'] = 'username';
  $dbSettings['password'] = 'password';
  $dbh = new dbConnection( $dbSettings );

  $a = array( 'phone' => 111111111, 'image' => "sadasdasd43eadasdad" );
  $dbh->insertArray('user', $a);

  // This will asume your table has a 'id' column, id: 1 will be updated in the example below:
  $dbh->updateArray('user', 1, $a);
?>
于 2015-01-07T18:26:20.897 に答える
0
public function insert($data = [] , $table = ''){
    $keys = array_keys($data);
    $fields = implode(',',$keys);
    $pre_fields = ':'.implode(', :',$keys);
    $query = parent::prepare("INSERT INTO $table($fields) VALUES($pre_fields) ");
    return $query->execute($data);
}
于 2021-07-15T19:48:47.123 に答える