0

3 つの用語 (検索パラメーター、郵便番号、アクティビティの種類) を含む検索ページがあります。

私はSQLを構成する関数を実行しました:(これは実際の関数ではなく、単純化された関数です)。フィルタリングするパラメーターを指定して使用することも、パラメーターを指定せずにすべてを取得することもできます。

function get_items($search="",$postal_code="",$activity=""){
global $db; //this is the $db=new mysqli(...) in other include file
$where="";
if ($s!=""){
    $s="%".$search."%";
    $where=" AND ((item.name like '".$s."') OR (item.description like '".$s."'))";
}
if($postal_code!=""){
    if (strlen($postal_code)==5){
         $where=" AND (item.postal_code like '".$postal_code."')";
    }
}

if($activity!=""){
    if (m_is_integer($postal_code)){ //m_is_integer returns true if is an integer
         $where=" AND (item.activity =".$activity.")";
    }
}
$sql="select ....... from -..... where .....".$where." order by ......"
//yes, I know I don't need to prepare the query 
$stmt=$db->prepare($sql); 
$result=$stmt->execute();
$stmt->store_result();
$item_array=Array();
if (($result!=false) && ($stmt->num_rows>0)){
     //do things and populate the array $item_array
}
$stmt->close();
return $item_array;
}

この関数は機能します。SQL は適切に構成されています。任意のパラメータを入力するか、何も入力せず、項目の配列を返します。

パラメータ化されたクエリを作成したいのですが、これが私のアプローチです:

function get_items_parametrized($search="",$postal_code="",$activity=""){
global $db; //this is the $db=new mysqli(...) in other include file
$where="";
$bind_array=Array();
if ($s!=""){
    $s="%".$search."%";
    $where=" AND ((item.name like ?) OR (item.description like ?))";
    $bii=Array("s",$s);
    $bind_array[]=$bii;
    $bii=Array("s",$s);
    $bind_array[]=$bii;
}
if($postal_code!=""){
    if (strlen($postal_code)==5){
         $where=" AND (item.postal_code like ?)";
         $bii=Array("s",$postal_code); //yes, is a string in the database
         $bind_array[]=$bii;
    }
}

if($activity!=""){
    if (m_is_integer($postal_code)){ //m_is_integer returns true if is an integer
         $where=" AND (item.activity = ?)";
         $bii=Array("i",$activity);
         $bind_array[]=$bii;
    }
}
$sql="select ....... from -..... where .....".$where." order by ......"
$stmt=$db->prepare($sql);
//go to bind data to search
$bind_type="";
$bind_params=Array();

foreach($bind_array as $b){
    $bind_type.=$b[0];
    $bind_params[]=$b[1];
    /* Approach 1: */
    $stmt->bind_param($b[0],$b[1]); 
}
/* Approach 2: */
$stmt->bind_param($bind_type,$bind_params); 
$result=$stmt->execute();
$stmt->store_result();
$item_array=Array();
if (($result!=false) && ($stmt->num_rows>0)){
     //do things and populate the array $item_array
}
$stmt->close();
return $item_array;
}

この関数は常に、空の $item_array Array () ではなく Array(Array(),Array()) を返します。これは、結果を正常にバインドしない場合に可能になります。実行は結果を返しません。

私もやろうとしました:

/* attempt 3 */
$data=Array();
$data[0]="";
foreach($bind_array as $b){
    $data[]=$b1;
    $bind_type.=$b[0];
}
$data[0]=$bind_type;

('ssi',$s,$postal_code,$activity) のような配列を作成して call_user_func_array() を呼び出すには:

call_user_func_array(array(&$stmt, 'bind_param'), $data);

私も試します:

call_user_func_array(array($stmt, 'bind_param'), $data);

そして、このアプローチはまだデータを返していません。

パラメータ化されたクエリで機能させるために、今何を試すことができますか?

どんな助けでも大歓迎です:D

4

1 に答える 1

1

答えは簡単です。プリペアド ステートメントでmysqli を使用しないでください。
準備済みステートメントでは使用できません。代わりに
PDOを使用してください。
これ答えです。Mysqli はあなたの問題であり、解決しなければなりません。

PDO を使用すると、コードが 3 倍短くなり、機能します。

mysqli を使い続けたい場合は、別の方法として、準備済みステートメントを取り除き、独自のプレースホルダーを実装することもできますが、ある程度の知識が必要です。ただし、条件付きクエリを簡単に作成できます。

$w = array();
$where = '';
if ($one) $w[] = $db->parse("one = ?s",$one); 
if ($two) $w[] = $db->parse("two IN (?a)",$two);
if ($tre) $w[] = $db->parse("tre <= ?i",$tre);
if (count($w)) $where = "WHERE ".implode(' AND ',$w);
$data = $db->getArr("SELECT * FROM table ?p LIMIT ?i,?i",$where, $start,$per_page);
于 2013-02-23T13:18:30.403 に答える