PHP Velho Oeste 2024

PDO::quote

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.2.1)

PDO::quote クエリ用の文字列をクオートする

説明

public PDO::quote(string $string, int $type = PDO::PARAM_STR): string|false

PDO::quote() は入力文字列のまわりに引用符を付け (必要であれば) 、 入力文字列にあるシングルクオートをエスケープします。その場合、 構成しているドライバに適したクオート形式が使用されます。

この関数を SQL の構築に使用する場合、 SQL ステートメントにユーザーの入力値を埋め込むための PDO::quote() を使用する代わりに、 バインドパラメータを用いて SQL を準備するための PDO::prepare() を使用することが強く推奨されます。 バインドパラメータを用いるプリペアドステートメントは、 補間されたクエリした場合に比べ、 移植性や利便性に優れ、SQL インジェクションに対する免疫力を持つだけでなく しばしばより高速で、サーバーやクライアント側でコンパイル済みの形式でクエリを キャッシュする事が可能です。

全ての PDO ドライバがこのメソッドを実装しているわけではありません (たとえば PDO_ODBC などの例があります)。 代わりにプリペアドステートメントを使用することを検討してください。

警告

セキュリティ: デフォルトの文字セット

サーバーレベルで設定するなりデータベース接続自身に設定させる (ドライバに依存します) なりして、 文字セットを明示しておく必要があります。この文字セットが PDO::quote() に影響を及ぼします。詳細は 各ドライバのドキュメント を参照ください。

パラメータ

string

クオートされる文字列を指定します。

type

クオートするスタイルを変更するため、 ドライバにデータ型のヒントを提供します。 たとえば PDO_PARAM_LOB は、 ドライバにバイナリデータをエスケープするように伝えます。

戻り値

理論上安全なクオートされた SQL ステートメントの文字列を返します。 ドライバがこの方法での引用符付けをサポートしていない場合は false を返します。

例1 通常の文字列をクオートする

<?php
$conn
= new PDO('sqlite:/home/lynn/music.sql3');

/* 単純な文字列 */
$string = 'Nice';
print
"Unquoted string: $string\n";
print
"Quoted string: " . $conn->quote($string) . "\n";
?>

上の例の出力は以下となります。

Unquoted string: Nice
Quoted string: 'Nice'

例2 危険な文字列をクオートする

<?php
$conn
= new PDO('sqlite:/home/lynn/music.sql3');

/* 危険な文字列 */
$string = 'Naughty \' string';
print
"Unquoted string: $string\n";
print
"Quoted string:" . $conn->quote($string) . "\n";
?>

上の例の出力は以下となります。

Unquoted string: Naughty ' string
Quoted string: 'Naughty '' string'

例3 複雑な文字列をクオートする

<?php
$conn
= new PDO('sqlite:/home/lynn/music.sql3');

/* 複雑な文字列 */
$string = "Co'mpl''ex \"st'\"ring";
print
"Unquoted string: $string\n";
print
"Quoted string: " . $conn->quote($string) . "\n";
?>

上の例の出力は以下となります。

Unquoted string: Co'mpl''ex "st'"ring
Quoted string: 'Co''mpl''''ex "st''"ring'

参考

add a note add a note

User Contributed Notes 6 notes

up
49
mirv
10 years ago
When converting from the old mysql_ functions to PDO, note that the quote function isn't exactly the same as the old mysql_real_escape_string function. It escapes, but also adds quotes; hence the name I guess :-)

After I replaced mysql_real_escape_string with $pdo->quote, it took me a bit to figure out why my strings were turning up in results with quotes around them. I felt like a fool when I realized all I needed to do was change ...\"".$pdo->quote($foo)."\"... to ...".$pdo->quote($foo)."...
up
7
nolife at gmail dot com
5 years ago
PDO quote (tested with mysql and mariadb 10.3) is extremely slow.

It took me hours of debugging my performance issues until I found that pdo->quote is the problem.

This function is far from fast, and it's PHP instead of C code:
function escape($value)
    {
        $search = array("\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a");
        $replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");

        return str_replace($search, $replace, $value);
    }

It is 50 times faster than pdo->quote()
(note, it's without quotes just escaping and only used here as an example)
up
23
col dot shrapnel at gmail dot com
10 years ago
One have to understand that string formatting has nothing to do with identifiers.
And thus string formatting should NEVER ever be used to format an identifier ( table of field name).
To quote an identifier, you have to format it as identifier, not as string.
To do so you have to

- Enclose identifier in backticks.
- Escape backticks inside by doubling them.

So, the code would be:
<?php
function quoteIdent($field) {
    return
"`".str_replace("`","``",$field)."`";
}
?>
this will make your identifier properly formatted and thus invulnerable to injection.

However, there is another possible attack vector - using dynamical identifiers in the query may give an outsider control over fields the aren't allowed to:
Say, a field user_role in the users table and a dynamically built INSERT query based on a $_POST array may allow a privilege escalation with easily forged $_POST array.
Or a select query which let a user to choose fields to display may reveal some sensitive information to attacker.

To prevent this kind of attack yet keep queries dynamic, one ought to use WHITELISTING approach.

Every dynamical identifier have to be checked against a hardcoded whitelist like this:
<?php
$allowed 
= array("name","price","qty");
$key = array_search($_GET['field'], $allowed));
if (
$key == false) {
    throw new
Exception('Wrong field name');
}
$field = $db->quoteIdent($allowed[$key]);
$query = "SELECT $field FROM t"; //value is safe
?>
(Personally I wouldn't use a query like this, but that's just an example of using a dynamical identifier in the query).

And similar approach have to be used when filtering dynamical arrays for insert and update:

<?php
function filterArray($input,$allowed)
{
    foreach(
array_keys($input) as $key )
    {
        if ( !
in_array($key,$allowed) )
        {
             unset(
$input[$key]);
        }
    }
    return
$input;
}
//used like this
$allowed = array('title','url','body','rating','term','type');
$data = $db->filterArray($_POST,$allowed);
// $data now contains allowed fields only
// and can be used to create INSERT or UPDATE query dynamically
?>
up
8
milosdj at gmail dot com
10 years ago
This function also converts new lines to \r\n
up
9
php at deobald dot org
15 years ago
Note that this function just does what the documentation says: It escapes special characters in strings.

It does NOT - however - detect a "NULL" value. If the value you try to quote is "NULL" it will return the same value as when you process an empty string (-> ''), not the text "NULL".
up
-55
aleksdimitrievski7 at gmail dot com
9 years ago
In foundation quoting is bad idea,there always will be possibillity to escape or fraud quote function ,better solution,i mean best solution is using this function : htmlentities($string, ENT_QUOTES, 'UTF-8') which translate quote into &#39; and $string translated like this can't affect on your code.
To Top