Есть ли лучший способ сделать фасетное меню?

обзор

Я создал фасетное меню для решения электронной коммерции своих компаний. Вы можете увидеть демо этого здесь. Все это состоит из нескольких сотен строк кода, распределенных по 4 файлам, поэтому я не буду здесь все включать, но вставлю любой соответствующий код.

Основной поток кода:

  1. Загрузить все товары для выбранной категории
  2. Загрузите все ограничения и фасеты (каждый фасет также загружает, какие продукты связаны с ним одновременно).
  3. Проверьте наличие активных фасетов, выбранных пользователем, и, если они есть, отфильтруйте исходный список продуктов по этим фасетам.
  4. Запустите запрос для каждого ограничения, чтобы подсчитать количество активных продуктов на один фасет, исключая любые активные фасеты в этом ограничении. Это связано с тем, что аспекты в ограничении не должны влиять друг на друга.

Я запускаю один запрос к базе данных, чтобы получить полный список допустимых продуктов для активных фасетов, а затем использую простую проверку in_array для исходного списка продуктов. Это фактический код, используемый на данный момент:

if(!empty($this->filters)) {

    //Get a list of product IDs that match the active facets
    $query = "SELECT p.pId 
        FROM products p 
        LEFT JOIN filterproducts fp 
        ON p.pId = fp.fpProductId 
        WHERE p.pDisplay <> 0 
        AND ( ";
    $or = "";
    foreach($this->filters as $constraint => $facets) {
        $query .= $or . "(";
        $subOr = "";
        foreach($facets as $facet => $set) {
            if($set) {
                $query .= $subOr . "fp.fpFacetId = " . (int)$facet;
                $subOr = " OR ";
            }
        }
        $query .= ")";
        $or = " OR ";
    }
    $query .= ") 
        GROUP BY p.pId 
        HAVING COUNT(p.pId) = " . count($this->filters);
    $results = $this->dbConn->query($query);
    if($this->dbConn->errno) {
        trigger_error('An error occured whilst loading products matching active facets.' . PHP_EOL . 'Query: ' . $query . PHP_EOL . 'Error[' . $this->dbConn->errno . ']: ' . $this->dbConn->error, E_USER_WARNING);
    } elseif($results->num_rows) {
        while($row = $results->fetch_assoc()) {
            $this->validProds[] = $row['pId'];
        }
        $results->free();
    }

    //Compare products with the list of valid IDs and unset any invalid products.
    foreach($this->products as $product) {
        if(!in_array($product->id, $this->validProds)) {
            unset($this->products[$product->id]);
        }
    }

}


Проблема

Затем я снова запускаю один и тот же запрос для каждого ограничения, но пропускаю активные фасеты этого ограничения из запроса. Вместо того, чтобы фильтровать продукты, я считаю количество совпадений и использую его для отображения числа рядом с именем фасета в меню. Однако это означает, что если у меня есть 10 ограничений, мне нужно выполнить 11 запросов (исходный плюс один для каждого ограничения). Хотя это работает, это не совсем эффективно.


Вопрос

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

0 ответов

Другие вопросы по тегам