ここでは、Zend Framework-1.11 による PHP から各種データベースへのクエリ発行時に行う SQL 文のクォート処理の実装例を掲載しています。エスケープによる SQL インジェクション対策は必須ともいえます。
スポンサーリンク
Oracle
protected function _quote($value) { if (is_int($value) || is_float($value)) { return $value; } $value = str_replace("'", "''", $value); return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; }
MySQL ( mysqli ) ※ 一部修正
protected function _quote($value) { if (is_int($value) || is_float($value)) { return $value; } $connect = mysqli_init(); return "'" . $connect->real_escape_string($value) . "'"; }
SQL Server
protected function _quote($value) { if (is_int($value)) { return $value; } elseif (is_float($value)) { return sprintf('%F', $value); } return "'" . str_replace("'", "''", $value) . "'"; }
DB2 ※ 一部修正
protected function _quote($value) { if (is_int($value) || is_float($value)) { return $value; } /** * Use db2_escape_string() if it is present in the IBM DB2 extension. * But some supported versions of PHP do not include this function, * so fall back to default quoting in the parent class. */ if (function_exists('db2_escape_string')) { return "'" . db2_escape_string($value) . "'"; } // db2_escape_string 関数未サポート環境の場合 if (is_int($value)) { return $value; } elseif (is_float($value)) { return sprintf('%F', $value); } return "'" . addcslashes($value, "\000\n\r\\'\"\032") . "'"; }
PDO
PDO ドライバの多くは quote メソッドを実装しているので そのまま使用することができますが、ZendFramework-1.11 によれば oracle の場合は実装する必要があるとのことです。
// Zend/Db/Adapter/Pdo/Oci.php 内のコメントから抜粋 /** * Quote a raw string. * Most PDO drivers have an implementation for the quote() method, * but the Oracle OCI driver must use the same implementation as the * Zend_Db_Adapter_Abstract class. * * @param string $value Raw string * @return string Quoted string */
Zend_Db で SQL をクォート ( Zend Framework-1.11 )
次に、実際に ZendFramework の Zend_Db アダプタを使用して SQL のクオート処理を行います。なお、処理結果は Zend_Db_Adapter_Oracle アダプタを使用した場合のものです。
// DB アダプタを取得 $adpt = Zend_Db::factory($config->database); // データベースへ接続 $adpt->getConnection(); // クォート処理(quote メソッド) $str = "I'am boy"; $quote = $adpt->quote($str); // クォート処理実施後の文字列 // 'I''am boy' // クォート処理(quoteInto メソッド) $into = "col1 = ?"; $quoteinto = $adpt->quoteInto($into, $str); // クォート処理実施後の文字列 // col1 = 'I''am boy' /* * この位置でSQL を組み立てて SQL の発行など行う。 */ // データベースから切断 $adpt->closeConnection();
サンプルの動作結果では正常に文字列がクォート処理が実施されていることが確認できます。 ただし、SQL 用に最適化されているため、文字列の前後にシングルコーテーションが自動で付与されています。なお、数値の場合はシングルコーテーションは付与されません。
文字列の前後のシングルクォーテーションを付与させない
Zend_Db_Expr クラスを使用することで文字列の前後のシングルコーテーションの自動付与をさせなくできます。例えば Oracle へのレコード挿入時に SYSDATE などで現在日時を設定している場合などのケースが考えられます。ただし、Zend_Db_Expr クラスを使用した場合はクォート処理も行われないので注意が必要です。
// select 文の発行 $str = "SYSDATE"; $quote = $adpt->quote(new Zend_Db_Expr($str)); // クォート処理実施後の文字列 // SYSDATE $into = "mdate = ?"; $quoteinto = $adpt->quoteInto($into, new Zend_Db_Expr($str)); // クォート処理実施後の文字列 // mdate = SYSDATE
Pingback: PHP5.4.0 でマジッククォートは削除されました ( magic_quotes_* ) – 勉強ダイエット