Переделывание поиска в VirtueMart. Добавление фильтрации по цене и производителю.

25.08.2012
Нужно было для магазина, поднятого на VirtueMart 1.1.6, сделать фильтр по цене, производителю и паре дополнительных полей.

Код модуля приводить не буду, это просто форма с несколькими чекбоксами и полями для цен.

Сосредоточимся на том , как обработать переданные параметры и сформировать запрос.

Формирование запроса происходит в файле:
/administrator/components/com_virtuemart/html/shop_browse_queries.php

Просмотрев файл, решил, что удобнее будет не дополнять уже готовые условия, а написать отдельную ветку, которая будет отрабатываться только для нового модуля.

Собственно код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
mm_showMyFileName( __FILE__ );

// Descending or Ascending Order? possible values: [ASC|DESC]
$DescOrderBy = strtoupper($vm_mainframe->getUserStateFromRequest( "browse{$keyword}{$category_id}{$manufacturer_id}DescOrderBy", 'DescOrderBy', "DESC" ));
$DescOrderBy = $DescOrderBy == 'ASC' ? 'ASC' : 'DESC';

  //Проверяем, пришли ли данные из модуля
  $shop_filter = JRequest::getVar('shop_filter', 0);
  if ($shop_filter)
  {
    $VM_BROWSE_ORDERBY_FIELDS = array(); // Отключение списка "Сортировать по"

    $fieldnames = "`real_{vm}_product`.`product_id`, `product_name`, `product_full_image`, `product_thumb_image`, `product_s_desc`, `product_parent_id`, `product_publish`, `product_in_stock`, `product_sku`, `product_url`, `product_weight`, `product_weight_uom`, `product_length`, `product_width`, `product_height`, `product_lwh_uom`, `product_available_date`, `product_availability`, `availability`, `real_{vm}_product`.`mdate`, `real_{vm}_product`.`cdate`";
    $count_name = "COUNT(DISTINCT `real_{vm}_product`.`product_sku`) as num_rows";
    $table_names = '`real_{vm}_product`';
    $join_array = array();
    $where_clause = array();

    $where_clause[] = 'product_publish = "Y"';
    $orderbyField = '`real_{vm}_product`.`product_sku`';

    $sf_price1 = JRequest::getVar('sf_price1', 0);
    $sf_price2 = JRequest::getVar('sf_price2', 0);
    if ($sf_price2)
    {
      $join_array[] = 'LEFT JOIN `real_{vm}_product_price` ON `real_{vm}_product`.`product_id` = `real_{vm}_product_price`.`product_id`';
      $where_clause[] = '`real_{vm}_product_price`.`product_price` BETWEEN '.$sf_price1.' AND '.$sf_price2.'';
    }


    // Производитель
    $aProduce = JRequest::getVar('sf_produce', array());
    if(count($aProduce))
    {
      $table_names .= ',`real_{vm}_product_mf_xref`';
      $where_clause[] = "`real_{vm}_product`.`product_id`=`real_{vm}_product_mf_xref`.`product_id` ";
      $aTmp = '';
      foreach($aProduce as $sf_produce)
      {
        switch ($sf_produce)
        {
          case '1': // HF
            $aTmp[] = '`real_{vm}_product_mf_xref`.manufacturer_id=4';
          break;

          case '2': // AEL
            $aTmp[] = '`real_{vm}_product_mf_xref`.manufacturer_id=3';
          break;

          case '3': // Ecotronic
            $aTmp[] = '`real_{vm}_product_mf_xref`.manufacturer_id=5';
          break;
        }
      }
      $where_clause[]  = ' (' . implode(' OR ', $aTmp) . ')';
    }

    // Тип:
    $aParam = JRequest::getVar('sf_type', array());
    if(count($aParam))
    {
      $bWith_lower_load = False;
      $aTmp = array();
      foreach($aParam as $sParam)
      {
        if ( $sParam == 3)
        {
          $bWith_lower_load = True;
        }
        else
        {
          $aTmp[] = 'type='.$sParam;
        }
      }

      if (count($aTmp))
      {
        $where_clause[]  = ' (' . implode(' OR ', $aTmp) . ')';
      }

      if ($bWith_lower_load)
      {
        $where_clause[]  = 'with_lower_load=1';
      }
    }

    // Охлаждение:
    $aParam = JRequest::getVar('sf_coolingtype', array());
    if(count($aParam))
    {
      $aTmp = '';
      foreach($aParam as $sParam)
      {
        $aTmp[] = 'coolingtype='.$sParam;
      }
      $where_clause[]  = ' (' . implode(' OR ', $aTmp) . ')';
    }


    $list  = "SELECT DISTINCT $fieldnames FROM ($table_names) ";
    $count  = "SELECT $count_name FROM ($table_names) ";



    if ($_SERVER['REMOTE_ADDR'] == '83.166.96.95')
    {
      echo  implode("\n AND ", $where_clause);
    }

    $q = implode("\n", $join_array ).' WHERE '. implode("\n AND ", $where_clause );
    $count .= $q;

//    $q .= "\n GROUP BY `real_{vm}_product`.`product_sku` ";
    $q .= "\n ORDER BY $orderbyField $DescOrderBy";

    // Joomla! 1.5 supports listing "All" items, which means $limit == 0
    if( vmIsJoomla(1.5) && $limit == 0 ) {
      $list .= $q;
    } else {
      $list .= $q . " LIMIT $limitstart, " . $limit;
    }

    if ($_SERVER['REMOTE_ADDR'] == '83.166.96.95')
    {
      echo '<br/><br/>'.nl2br(str_replace('real_{vm}', 'jos_vm', $list));
    }

    // Store current GET parameters for usage on the product details page navigation
    $_SESSION['last_browse_parameters'] = array(
                                            'category_id' => $category_id,
                                            'manufacturer_id' => $manufacturer_id,
                                            'keyword' => $keyword,
                                            'keyword1' => $keyword1,
                                            'keyword2' => $keyword2,
                                            'featured' => $featured,
                                            'discounted' => $discounted
                                        );
    if( !empty($product_type_id) ) {
      $_SESSION['last_browse_parameters']['product_type_id'] = $product_type_id;
    }


  }
   else
   {
//Далее идет оригинальный код

Пара дополнений к задаче:

  1. Нужно было убрать «сортировать по:»

    В приведенном примере уже есть решение этой задачи:

    $VM_BROWSE_ORDERBY_FIELDS = array();

  2. Также убрать постраничное деление

    В файле: /administrator/components/com_virtuemart/html/shop.browse.php

    Заменяем код

    1
    2
    3
    4
    5
    // Prepare Page Navigation
       require_once( CLASSPATH . 'pageNavigation.class.php' );
       $pagenav = new vmPageNav( $num_rows, $limitstart, $limit );
       $tpl->set( 'pagenav', $pagenav );
    

    На

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
        // Prepare Page Navigation
          // Oddler
          $shop_filter = JRequest::getVar('shop_filter', 0);
          if (!$shop_filter)
          {
            require_once( CLASSPATH . 'pageNavigation.class.php' );
            $pagenav = new vmPageNav( $num_rows, $limitstart, $limit );
            $tpl->set( 'pagenav', $pagenav );
          }
          else
          {
            $tpl->set( 'pagenav', '' );
          }

Категории: VirtueMart 1.X
Яндекс.Метрика