web-dev-qa-db-ja.com

PHP PDO :: bindParam()データ型..どのように機能しますか?

bindParam() (または bindValue() )のデータ型の宣言は何に使用されるのでしょうか...

つまり、整数の引数を定義すると(PDO::PARAM_INT)、引数は次のような整数に変換する必要があります

$delete->bindParam(1, $kill, PDO::PARAM_INT);
// should work like
$delete->bindParam(1, (int)$kill);

または、引数が宣言された型でない場合は、少なくともエラーをスローします。しかし、そうではありません。

調べてみると、php.netアーカイブで次のことがわかりました。

こんにちは、みんな、

私は現在PDOに取り組んでいます。まさにbindParam()関数です。 3番目のパラメーターdata_typeは、値の型を強制するためにここにあるようです。しかし、私が試してみると:

$sql = "INSERT INTO produit (idproduit, nom, marque) VALUES (NULL, :nom, :marque)";
$stmt = $dbh->prepare($sql);
$nom = 'Testarossa'; $marque = 'Ferrari' ;
$stmt->BindValue(':marque',$marque) ;
$stmt->BindParam(':nom',$nom,PDO::PARAM_INT) ;

$stmt->execute(); $nom = '250 GTO' ;
$stmt->execute(); ?>

データベースにPHPエラーまたは干渉が発生することを期待していましたが、DBには次のようなものがあります。

22テスタロッサフェラーリ23250GTOフェラーリ

これは、3番目のパラメーターがあるかどうかに関係なく変更されなかったことを意味します。または多分私は何かが恋しいです。誰かが私をもっと苦しめることができますか?または、誰かが私にそれに関する情報を見つけることができる場所を教えてもらえますか?.

よろしく、

サイラス

それはまさに私の状況です。私の考えはどこで間違っていますか?

30
Strae

他の言語の他のDB抽象化フレームワークでは、インライン値の適切なエスケープを実行していることを確認したり(適切なバインドされたパラメーターをサポートしていないドライバーの場合)、数値が適切にパックされたバイナリ(与えられたプロトコルサポート)。 PDOのように見えますが、あまり効果がありません。

   if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && ! ZVAL_IS_NULL(param->parameter)) {
                if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
                        char *p;
                        int len = spprintf(&p, 0, "%F", Z_DVAL_P(param->parameter));
                        ZVAL_STRINGL(param->parameter, p, len, 0);
                } else {
                        convert_to_string(param->parameter);
                }
        } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
                convert_to_long(param->parameter);
        } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(param->parameter) == IS_LONG) {
                convert_to_boolean(param->parameter);
        }

したがって、それがSTRであると言う場合(または、それがデフォルトであるため、何も言わない場合)、データの内部型がdoubleである場合、1を使用して文字列に変換されます。メソッド、それがdoubleでない場合は、別のメソッドを使用して文字列に変換します。

あなたがそれがintであると言うが、それが本当にブールであるならば、それはそれをlongに変換するでしょう。

ブール値であると言っても実際には数値である場合は、真のブール値に変換されます。

Stmtソースを(すばやく)見てきたのはこれだけです。パラメーターをドライバーに渡すと、追加の魔法を実行できると思います。ですから、あなたが得るのは、少しでも正しいことをすることと、ドライバー間の行動のあいまいさと差異がたくさんあることだと思います。

32
Trey

そこで、PHPソースコードに飛び込むことにしました。これが私が見つけたものです。

static int really_register_bound_paramバージョン5.2.9の329行目のext/pdo /pdo_stmt.cにあります

if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && ! ZVAL_IS_NULL(param->parameter)) {
    if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
        char *p;
        int len = spprintf(&p, 0, "%F", Z_DVAL_P(param->parameter));
        ZVAL_STRINGL(param->parameter, p, len, 0);
    } else {
        convert_to_string(param->parameter);
    }
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && Z_TYPE_P(param->parameter) == IS_BOOL) {
    convert_to_long(param->parameter);
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(param->parameter) == IS_LONG) {
    convert_to_boolean(param->parameter);
}

これらは、PDOがバインディング中に行う変換です。

  • PDO :: PARAM_STRは、指定したものをnull以外の文字列に変換します。
  • PDO :: PARAM_INTは、boolをlongに変換します
  • PDO :: PARAM_BOOLは、longをboolに変換します

それでおしまい。他に何も変換されません。 PDOは、PARAMフラグを使用して、データ型をキャストしないようにSQLをフォーマットします。

21
gradbot

PDO :: PARAM_INTが及ぼす影響は少なくとも1つあります インサート クエリ:ブール値は0または1に変換されます。

$i = true;
$stmt->bindParam(':i', $v, PDO::PARAM_INT);

pdo_stmt.c:

else if(PDO_PARAM_TYPE(param-> param_type)== PDO_PARAM_INT && Z_TYPE_P(param-> parameter)== IS_BOOL){
 convert_to_long(param-> parameter); 
}
6
VolkerK

BindValueで同じことを試したところ、同じ結果が得られたため、表示される動作はbindParamに限定されません。

$stmt->BindValue(':marque', $marque) ;
$stmt->BindValue(':nom', $nom, PDO::PARAM_INT) ;

$stmt->execute();
$nom = '250 GTO';
$stmt->BindValue(':nom', $nom, PDO::PARAM_INT) ;
$stmt->execute(); 
3
gradbot