2011-08-03 15 views
0

ブランド、商品カテゴリ、価格帯(注文とは無関係)に基づいて同じ検索を絞り込むために、多段階検索を作成しようとしています。複数レベルフィルタに基づく検索結果の絞り込みMysql + PHP

私は自分の問題を説明する方法を提供しているため、次の実装は機能しない場合があります。

テーブル: 製品

| id | name | price_id | 
| 1 | test1 |  1  | 
| 2 | test2 |  2  | 
| 3 | test3 |  1  | 

prices_ranges

| id | price_from | price_to | 
| 1 |  100  | 200 | 
| 1 |  200  | 300 | 

product_attributes

| product_id | id_attribute | 
|  1  |  1  | 
|  1  |  2  | 
|  1  |  3  | 
|  1  |  5  | 
|  2  |  5  | 
|  2  |  3  | 
|  3  |  5  | 

属性

| id | name  | 
| 1 | attr1 | 
| 2 | attr2 | 
| 3 | attr3 | 
| 4 | attr4 | 
| 5 | attr5 | 
| 6 | attr6 | 
| 7 | attr7 | 

私は引数を$ _GETを通してURLに渡しています。そして、複数のフィルタの検索のための私のコードは次のように多少のようになります。

//this generates the base query 
$dynamicsql = get_by_filters(); 

//does the group by to discard duplicated products 
$filtersql= $dynamicsql."group by p.id"; 
$query = mysql_query($filtersql) or die(mysql_error()); 
//the data is now ready to be presented but 
$total = mysql_num_rows($query); 
for($i=0; $i<$total; $i++): 
     $prods[$i] = mysql_fetch_object($query); 
    endfor; 

//first let's build the html code for filtering the results 
list_prices_filter($dynamicsql); 

//i'll only show the code for the bellow function. the above is pretty similar 
list_attr_filter($dynamicsql); 


//now i print the results 
foreach($prods as $prod): 
     //for the porpuse of this question will only print the product name 
     echo $prod['pname']; 
endforeach; 

機能フィルターベースのクエリを返すために

function get_by_filters(){ 

     $dynamicsql = "SELECT p.name as pname,p.price_from,p.price_to,a.name,a.id FROM `products` p "; 
     $dynamicsql .= "left JOIN `price_ranges` pr ON p.price_id = pr.id "; 
     $dynamicsql .= "LEFT JOIN `product_attributes` pa ON w.id = pa.product_id "; 
     $dynamicsql .= "LEFT JOIN `attributes` a ON a.uid = pa.id_attribute where 1=1 "; 

     foreach($_GET as $parameter=>$value): 
       switch($parameter): 

        case 'price': 
      $dynamicsql .= " AND p.price = ".$value; 
      break; 

        //filtro por zip code 
        case 'attr': 
         $dynamicsql .= " AND a.id = ".$value; 
         break; 
        default: 
         $dynamicsql .= "AND ".$parameter." = ".$value." "; 
        break; 
       endswitch; 
     endforeach; 

     return $dynamicsql; 
} 

属性選択を一覧表示する機能:

function get_special_care($dynamicsql){ 

    $sql = "SELECT * FROM attributes a"; 
    $query = mysql_query($sql); 
    $total = mysql_num_rows($query); 

    $output = '<ul>'; 
    for($i=0; $i<$total;$i++): 
     $result[$i] = mysql_fetch_object($query); 
     $active = ($_GET['attr'] == $result[$i]->uid) ? 'active':''; 

     $workerstotal = mysql_query($dynamicsql . " and a.id ={$result[$i]->uid} group by p.id"); 
     $totalworkers = mysql_num_rows($workerstotal); 

     $output .= ' 
      <li class="'.$active.'"> 
       <a href="'.url_increment('attr='.$result[$i]->uid).'">'.$result[$i]->name.'<span class="totalfound">('.$totalworkers.')</span></a> 
       <a title="Remove" href="'.url_decrement('attr').'" class="remove-criteria"><img src="'image_src_url" alt="Remove" /></a> 
      </li>'; 
    endfor; 

    $output .= '</ul>'; 
    echo $output; 
} 

機能url_increment()およびurl_decrementは、そのフィルタをURLに追加または削除するだけです。私はそれが問題に関連していないと思うので、それをリストアップしていません。

よく紹介!私の問題は、ユーザーが最初のステップで属性5を選択した場合、コードは製品1,2および3を示しますが、属性を再度フィルタリングできないことです。

この場合、get_special_care($ dynamicsql)関数は、属性1,2の製品が0で、製品1には1つ、商品1と2には2つの一致が必要です。

私はこれが原因で、ベースのクエリを生成する関数である、ほぼ確信している:

case 'attr': 
    $dynamicsql .= " AND a.id = ".$value; 
    break; 
default: 

しかし、私はこの問題を解決する方法を見つけ出すことはできません。

また、URLがwww.teste.com/search & attr = 5のように見える最初の属性を選択すると、このコードには別の問題があります。 (ユーザーが属性1をクリックしたとする)URLはwww.teste.com/search & attr = 5 & attr = 1となりますが、これも問題です(私は思います)

誰でも助けてもらえますか?私はあなたの多くが同様のアルゴリズムを実装していると思います。

最後に長いポスト申し訳ありませんが、私は自分自身を説明したかったし、多分それは、将来の助けのための基準となる...事前に

感謝!!私がこれまでに見つけることができ

+0

こんにちは、あなたが本当に機能して何が起こっているのか理解を助けるために、すべてのクエリの実行時にエコーしてみてください。それは、複雑なSQL生成アルゴリズムで多くを助けます。たとえば、すべてのurl属性とSQLをエコーし​​ます。出力はurl属性のように ""、SQLは "" – Will

+0

こんにちは!応答していただきありがとうございます。私はそれをして、問題がここにあるように見える "$ dynamicsql。=" AND a.id = "。$ value;"私は基本的に、そのattribute_idに関連付けられた結果のみを返すようにsqlに指示していますが、問題は私が望むものと一致するようにsqlを変更できないということです... – jribeiro

+1

get_special_care($ dynamicsql) – Will

答えて

1

次のように私はこの問題を解決するために管理:

は、URLからすべてのatributesを取得する関数を作成した(通常の$ _GET [「名前」] ONYリターンはwww.test.com/のようなURLに= 5属性= 5

function getFilter(){ 
     $query = explode('&', $_SERVER['QUERY_STRING']); 
     $params = array(); 
    foreach($query as $param) 
    { 
     list($name, $value) = explode('=', $param); 
     $params[urldecode($name)][] = urldecode($value); 
    } 
    return $params; 

} 

?MOD =検索&属性= 2 &属性が、私は

function get_by_filters(){ 

    $dynamicsql = "SELECT p.name as pname,p.price_from,p.price_to,a.name,a.id FROM `products` p "; 
    $dynamicsql .= "left JOIN `price_ranges` pr ON p.price_id = pr.id "; 
    $dynamicsql .= "LEFT JOIN `product_attributes` pa ON w.id = pa.product_id "; 
    $dynamicsql .= "LEFT JOIN `attributes` a ON a.uid = pa.id_attribute where 1=1 "; 

    foreach($_GET as $parameter=>$value): 
      switch($parameter): 

       case 'price': 
     $dynamicsql .= " AND p.price = ".$value; 
     break; 

       //changes here 
       case 'attr': 
        $get = tools::getFilter(); 
      foreach ($get['attr'] as $attrs => $value) { 
     $filter .= " and w.uid in (select a from `product_attributes` where attribute_id= {$value}) "; 
        } 
       default: 
        $dynamicsql .= "AND ".$parameter." = ".$value." "; 
       break; 
      endswitch; 
    endforeach; 

    return $dynamicsql; 
} 

し、最終的に我々ヘクタール機能get_by_filtersを変更しましたすべてのアクティブな属性を提示しましことはので、私は、この関数はこれを好きに変更フィルタ:

function get_special_care($dynamicsql){ 

    $sql = "SELECT * FROM attributes a"; 
    $query = mysql_query($sql); 
    $total = mysql_num_rows($query); 

    //changes here   
    $get = tools::getFilter(); 

    $output = '<ul>'; 
    for($i=0; $i<$total;$i++): 
     $result[$i] = mysql_fetch_object($query); 

     //changes here 
     foreach ($get['attr'] as $attr => $value) { 
     $active = ($value == $result[$i]->uid) ? 'active':$active; 
    } 


     $workerstotal = mysql_query($dynamicsql . " and a.id ={$result[$i]->uid} group by p.id"); 
     $totalworkers = mysql_num_rows($workerstotal); 

     $output .= ' 
      <li class="'.$active.'"> 
       <a href="'.url_increment('attr='.$result[$i]->uid).'">'.$result[$i]->name.'<span class="totalfound">('.$totalworkers.')</span></a> 
       <a title="Remove" href="'.url_decrement('attr').'" class="remove-criteria"><img src="'image_src_url" alt="Remove" /></a> 
      </li>'; 
    endfor; 

    $output .= '</ul>'; 
    echo $output; 
} 
1

のみエラーが

case 'price': $dynamicsql .= " AND p.price = ".$value; 

p.priceは、価格フィールドを持っていないあなたの元の製品テーブルのproducts.price、を参照してくださいです。

クエリの例外はありますか?

+0

こんにちは!それはまたタイプミスでした。私の実際のコードははるかに複雑で、厄介な混乱を招くでしょう。申し訳ありません。 – jribeiro

+0

ああ、コードでは "本当の"問題ではなかった:) – jribeiro