0

PHP プロジェクトのデータベースで 29 のフィールドを検索しようとしています。データベースへの接続に mysqli を使用しています。bind_param() を使用しないとクエリは正常に動作しますが、次のエラーで失敗します。

PHP Warning:  mysqli_stmt::bind_param() [<a href='mysqli-stmt.bind-param'>mysqli-stmt.bind-param</a>]: Number of variables doesn't match number of parameters in prepared statement in /search.php on line 6

私のコードは次のとおりです。

<?php 
$find = $_POST['find'];
if (strcasecmp($_POST['in'], 'users') == 0) {

$query = $db->prepare("SELECT u.id, u.group_id, u.username, u.email, m.credits, m.first_name, m.last_name, m.address1, m.address2, m.city, m.state, m.country, m.zipcode, m.about, m.account_status, m.vacation_status FROM kf_users u JOIN kf_usermeta m ON u.id = m.id WHERE u.id LIKE  '%?%' OR u.group_id LIKE  '%?%' OR u.ip_address LIKE  '%?%' OR u.username  LIKE  '%?%' OR u.password LIKE  '%?%' OR u.salt LIKE  '%?%' OR u.email LIKE  '%?%' OR u.activation_code LIKE  '%?%' OR u.forgotten_password_code LIKE  '%?%' OR u.remember_code LIKE  '%?%' OR u.created_on LIKE  '%?%' OR u.last_login LIKE '%?%' OR u.active LIKE  '%?%' OR u.FUID LIKE  '%?%' OR m.id LIKE  '%?%' OR m.credits LIKE  '%?%' OR m.rating LIKE  '%?%' OR m.user_id LIKE  '%?%' OR m.first_name LIKE  '%?%' OR m.last_name LIKE  '%?%' OR m.address1 LIKE  '%?%' OR m.address2 LIKE  '%?%' OR m.city LIKE  '%?%' OR m.state LIKE  '%?%' OR m.country LIKE  '%?%' OR m.zipcode LIKE  '%?%' OR m.about LIKE  '%?%' OR m.account_status LIKE  '%?%' OR m.vacation_status LIKE '%?%'");
$query->bind_param('sssssssssssssssssssssssssssss',$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find,$find);
$query->execute();
$query->bind_result($id, $group, $username, $email, $credits, $first_name, $last_name, $address1, $address2, $city, $state, $country, $zipcode, $about, $account_status, $vacation_status);

while ($query->fetch()) {
    $result['id'] = $id;
    $result['group'] = $group;
    $result['username'] = $username;
    $result['email'] = $email;
    $result['credits'] = $credits;
    $result['first_name'] = $first_name;
    $result['last_name'] = $last_name;
    $result['address1'] = $address1;
    $result['address2'] = $address2;
    $result['city'] = $city;
    $result['state'] = $state;
    $result['country'] = $country;
    $result['zipcode'] = $zipcode;
    $result['about'] = $about;
    $result['account_status'] = $account_status;
    $result['vacation_status'] = $vacation_status; 
    $output[] = $result;
}

$query->close();

}
?>

ここでも、bind_param() 行をコメント アウト?し、クエリの を検索用語に置き換えると、データが返されますが、そのままではエラーが発生し、データがありません。ここで何が問題になるのか、誰にもアイデアはありますか?

4

3 に答える 3

3

?クエリは29で、リストには29のsデータ型エントリがあり、バインドする変数は29ですが、プレースホルダーを引用符で囲むと、プレースホルダーではなくなり、単なる文字列になります。したがって、MySQLはバインドされるパラメータがゼロであると認識しており、29をバインドしようとしています。bind_param$find?

プリペアドステートメントを使用して簡単なLIKE句を実行するには、次のようにします。

$query = $db->prepare("SELECT * FROM some_table WHERE field LIKE ?");
$query->bind_param('s',$find);

あなたの場合、あなたは一致したいです%$find%。これは次の方法で実行できます。

$query = $db->prepare("SELECT * FROM some_table WHERE field LIKE ?");
$query->bind_param('s', '%'.$find.'%');

または、さらに複雑な場合はCONCAT()、すべてのパラメーターで使用できます。

$query = $db->prepare("SELECT * FROM some_table WHERE field LIKE CONCAT('%', ?, '%')");
$query->bind_param('s',$find);

既存のコードと最初の方法を使用したコピーと貼り付け('%'.$find.'%')

$query = $db->prepare("SELECT u.id, u.group_id, u.username, u.email, m.credits, m.first_name, m.last_name, m.address1, m.address2, m.city, m.state, m.country, m.zipcode, m.about, m.account_status, m.vacation_status FROM kf_users u JOIN kf_usermeta m ON u.id = m.id WHERE u.id LIKE ? OR u.group_id LIKE ? OR u.ip_address LIKE ? OR u.username  LIKE ? OR u.password LIKE ? OR u.salt LIKE ? OR u.email LIKE ? OR u.activation_code LIKE ? OR u.forgotten_password_code LIKE ? OR u.remember_code LIKE ? OR u.created_on LIKE ? OR u.last_login LIKE ? OR u.active LIKE ? OR u.FUID LIKE ? OR m.id LIKE ? OR m.credits LIKE ? OR m.rating LIKE ? OR m.user_id LIKE ? OR m.first_name LIKE ? OR m.last_name LIKE ? OR m.address1 LIKE ? OR m.address2 LIKE ? OR m.city LIKE ? OR m.state LIKE ? OR m.country LIKE ? OR m.zipcode LIKE ? OR m.about LIKE ? OR m.account_status LIKE ? OR m.vacation_status LIKE ?");
$query->bind_param('sssssssssssssssssssssssssssss','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%','%'.$find.'%');
于 2012-12-04T05:31:29.283 に答える
2

バインディングパラメータは文字列補間と同じではありません。変数を単に置き換えることはできません?。また、引用符で囲むこともできません。プレースホルダーは値全体を表します。

代わりに、次のようにクエリを準備する必要があります

$query = $db->prepare('SELECT ... WHERE u.id LIKE ? OR u.group_id LIKE ? ... ');

次に、値をワイルドカード文字でラップします

$find = '%' . $find . '%';

アップデート

MySQLiの代わりにPDOを使用することを強くお勧めします。これを使用すると、たとえば、名前付きプレースホルダーを使用できます

$stmt = $pdo->prepare('SELECT ... WHERE u.id LIKE :term OR u.group_id LIKE :term ... ');
$find = '%' . $find . '%';
$stmt->bindParam('term', $find);
$stmt->execute();

このようにして、クエリ全体で同じプレースホルダーを再利用できます

于 2012-12-04T05:31:49.647 に答える
-1

これが機能しない場合は、mysql の代わりに mariadb を使用している可能性があります。この問題は、両者の微妙な違いです。

私が自分のコードで行ったことは、次のように変更することです。

$search_text=$db->real_escape_string($search_text);
$stmt=$db->prepare("SELECT * FROM rentals WHERE search_text LIKE '%{$search_text}%'");
//TODO Put the bind_param back when it works someday; plus take out the escape.
//$stmt=$db->prepare("SELECT * FROM rentals WHERE search_text LIKE ?");
//$stmt->bind_param('s', '%'.$search_text.'%');
$stmt->execute();

粗雑ですが、当面は実用的なソリューションです。

于 2013-09-24T21:57:03.507 に答える