9

mysql_*()ext / mysql(関数)を使用したコードの一部をPDOとプリペアドステートメントに変換しています。以前は、クエリを動的に作成していたときに、文字列を渡してクエリにmysql_real_escape_string()直接ドロップしていましたが、クエリを実行するときに値を配列として渡すか、実行前に変数をバインドする必要があります。

古いコードを新しいデータベースドライバーを使用するように変換するにはどうすればよいですか?

4

1 に答える 1

15

クエリをext/mysqlからPDOプリペアドステートメントに移行するには、いくつかの側面への新しいアプローチが必要です。ここでは、定期的に実行する必要があるいくつかの一般的なタスクについて説明します。これは、考えられるすべての状況に完全に一致するわけではなく、クエリを動的に生成するときに使用できるいくつかの手法を示すことを目的としています。

始める前に、覚えておくべきことがいくつかあります。何かが正しく機能しない場合は、質問する前にこのリストを確認してください。

  • エミュレートされた準備を明示的に無効にしない場合、クエリはを使用するよりも安全ではありませんmysql_real_escape_string()完全な説明については、これを参照してください。
  • 名前付きプレースホルダーと疑問符プレースホルダーを1つのクエリに混在させることはできません。クエリの作成を開始する前に、もう一方を使用することを決定する必要があります。途中で切り替えることはできません。
  • プリペアドステートメントのプレースホルダーは値にのみ使用でき、オブジェクト名には使用できません。つまり、プレースホルダーを使用して、データベース、テーブル、列、関数の名前、またはSQLキーワードを動的に指定することはできません。一般に、これを行う必要がある場合は、アプリケーションの設計が間違っているため、再検討する必要があります。
  • データベース/テーブル/列の識別子を指定するために使用される変数は、ユーザー入力から直接取得しないでください。つまり、、、または外部ソースからのその他のデータを使用$_POST$_GET$_COOKIE列名を指定しないでください。動的クエリを作成するために使用する前に、このデータを前処理する必要があります。
  • PDOの名前付きプレースホルダーは、クエリでとして指定されます:name。実行のためにデータを渡す場合、対応する配列キーにはオプションで先頭:を含めることができますが、必須ではありません。プレースホルダー名には、英数字のみを含める必要があります。
  • 名前付きプレースホルダーは、クエリで複数回使用することはできません。同じ値を複数回使用するには、複数の異なる名前を使用する必要があります。繰り返し値が多いクエリがある場合は、代わりに疑問符のプレースホルダーを使用することを検討してください。
  • 疑問符のプレースホルダーを使用する場合、渡される値の順序が重要です。プレースホルダーの位置は0インデックスではなく、1インデックスであることに注意することも重要です。

以下のすべてのサンプルコードは、データベース接続が確立されており、関連するPDOインスタンスが変数に格納されていることを前提としています$db


列/値リストとしての連想配列の使用

これを行う最も簡単な方法は、名前付きプレースホルダーを使用することです。

ext / mysqlを使用すると、クエリが作成されたときに値をエスケープし、エスケープされた値をクエリに直接配置します。PDOプリペアドステートメントを作成するときは、代わりに配列キーを使用してプレースホルダー名を指定するため、配列をに直接渡すことができPDOStatement::execute()ます。

この例では、3つのキーと値のペアの配列があります。ここで、キーは列名を表し、値は列の値を表します。いずれかの列が一致するすべての行を選択します(データにはOR関係があります)。

// The array you want to use for your field list
$data = array (
  'field1' => 'value1',
  'field2' => 'value2',
  'field3' => 'value3'
);

// A temporary array to hold the fields in an intermediate state
$whereClause = array();

// Iterate over the data and convert to individual clause elements
foreach ($data as $key => $value) {
    $whereClause[] = "`$key` = :$key";
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE '.implode(' OR ', $whereClause).'
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

IN (<value list>)配列を使用して句の値リストを作成する

これを実現する最も簡単な方法は、疑問符のプレースホルダーを使用することです。

ここに、指定された列名と照合する5つの文字列の配列があり、列の値が5つの配列値の少なくとも1つと一致するすべての行を返します。

// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Construct an array of question marks of equal length to the value array
$placeHolders = array_fill(0, count($data), '?');

// Normalise the array so it is 1-indexed
array_unshift($data, '');
unset($data[0]);

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($data);

名前付きプレースホルダーを使用してクエリを使用することを既に決定している場合、この手法はもう少し複雑ですが、それほど多くはありません。配列をループして連想配列に変換し、名前付きプレースホルダーを作成するだけです。

// The array of values
$data = array (
  'value1',
  'value2',
  'value3',
  'value4',
  'value5'
);

// Temporary arrays to hold the data
$placeHolders = $valueList = array();

// Loop the array and construct the named format
for ($i = 0, $count = count($data); $i < $count; $i++) {
  $placeHolders[] = ":list$i";
  $valueList["list$i"] = $data[$i];
}

// Construct the query
$query = '
  SELECT *
  FROM `table_name`
  WHERE `field` IN ('.implode(', ', $placeHolders).')
';

// Prepare the query
$stmt = $db->prepare($query);

// Execute the query
$stmt->execute($valueList);
于 2012-09-08T01:40:44.327 に答える