18
$sql = "SELECT * FROM table WHERE id LIKE CONCAT('%', :id, '%')
LIMIT :limit1, :limit2";

次のように配列入力を引き続き使用したい:

$stmt->execute($array);

そうしないと、クエリを実行するために同じメソッドを再利用できません。

同時に、:limit1 と :limit2 は、次のように配置しない限り機能しません。

$stmt->bindParam(':limit1', $limit1, PDO::PARAM_INT);

両方を実行しようとしましたが、bindParams では実行されません:

$stmt->bindParam(':limit2', $limit2, PDO::PARAM_INT);
$stmt->execute($array);

それを回避する方法は何ですか?

PDOStatement を拡張して新しいメソッド「bindLimit」などを追加できると考えましたが、PDO がパラメータを変数にバインドするために使用する内部メソッドがわかりません。

4

3 に答える 3

18

のデフォルト設定をオフにすると、機能しPDO::ATTR_EMULATE_PREPARESます。mysqlのデフォルトでその設定がオンになっていることがわかりました。つまり、実際に準備されたステートメントを使用することはありません。phpは内部的に動的SQLを作成し、値を引用してプレースホルダーを置き換えます。ええ、主要なwtf。

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $pdo->prepare($sql);
$stmt->execute(array(5)); //works!

パフォーマンス上の理由から、prepare はデフォルトでエミュレートされます。

PDO MySQL: Use PDO::ATTR_EMULATE_PREPARES or not?も参照してください。

于 2012-05-03T19:24:24.313 に答える
8

のドキュメントに記載されているとおりPDOStatement::execute

input_parameters

実行中の SQL ステートメントにバインドされたパラメーターと同じ数の要素を持つ値の配列。すべての値は として扱われPDO::PARAM_STRます。

ほとんどの場合、MySQL の暗黙的な型変換が残りを処理するため、これはまったく見過ごされます(ただし、MySQL が特に奇妙な接続文字セットを使用している場合、望ましくない動作を引き起こす可能性があります。期待される結果)。

LIMITあなたの場合、MySQL は文字列引数を持つ句を実行しようとしています。暗黙的な型変換を使用してそれを解決しようとすることはできますが、整数があるべき場所に文字列が表示される他の場所と同様に、単に気にせず、代わりに泣いてしまいます。

したがって、これらの特定のパラメーターが整数であることを PDO に伝える必要があります。PHP でさえ、その変数の型がわからないので、それを行う唯一の方法は、PDOStatement::bindParamまたはPDOStatement::bindValueあなたが行っているように直接バインドすることだと思います (ただし、引数を単純なキャストとして指定する必要はありませが)。これにより、PHP の無知な型システムが十分に機能するようになります)。$data_type(int)$variable

パラメータを変数にバインドするために PDO が使用する内部メソッドに関する限り、really_register_bound_param()(当然のことながら PHP には公開されていないため、C で多くのことを楽しむことができます) を参照してください。

幸運を!

于 2012-05-03T19:10:32.653 に答える