PHP PDO :: bindParam()データ型..どのように機能しますか?
-
08-07-2019 - |
質問
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のいずれかが期待されていました データベース内のエラーまたはinterger。 しかし、私のDBには:
があります22テスタロッサフェラーリ23250 GTO フェラーリ
それは、私が変わっても変わらなかったことを意味します 3番目のパラメーターがあるかどうか。または たぶん何かが恋しいです。誰かできますか もっと私を助けた?またはただ誰かができます どこで情報を見つけられるか教えてくれた それについて。
よろしく、
サイラス
それはまさに私の状況です。私の考えはどこで間違っているのですか?
解決
他の言語の他の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であるが実際にはboolであると言う場合、それはlongに変換されます。
boolであるが実際には数値であると言う場合、真のブール値に変換します。
これは、実際にstmtソースを(すばやく)見たすべてです。ドライバーにパラメーターを渡すと、追加の魔法ができると思います。だから、あなたが得るのは、少しだけ正しいことと、ドライバー間の行動のあいまいさと分散の多くです。
他のヒント
だから私はPHPソースコードに飛び込むことにしました。これが私が見つけたものです。
static int really_register_bound_param
ext / pdo / pdo_stmt.cのバージョン5.2.9の329行目
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をブールに変換します
それだけです。それ以外は変換されません。 PDOはPARAMフラグを使用して、データ型をキャストしないようにSQLをフォーマットします。
INSERT クエリに対する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); }
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();