Облако брендов для SimplaCMS 2.1+

Открывает файл api/Brands.php и перед методом get_brand (~37 строка) добавляем наш

public function get_brands_weight($filter = array())
{
    $brands = array();
    $category_id_filter = '';
    if(!empty($filter['category_id']))
      $category_id_filter = $this->db->placehold('LEFT JOIN s_products_categories pc ON p.id = pc.product_id WHERE pc.category_id in(?@)', (array)$filter['category_id']);

    // Выбираем все бренды
    $query = $this->db->placehold("SELECT DISTINCT b.id, b.name, b.url, COUNT(p.id) AS `count`
                     FROM s_brands b LEFT JOIN s_products p ON p.brand_id=b.id $category_id_filter 
                     WHERE p.visible = 1
                     GROUP BY b.id ORDER BY b.name");
    $this->db->query($query);

    return $this->db->results();
}

По сути мы создали копию выборки группы брендов, но уже с учетом весов. Менять базовые методы в данном случае не рекомендую, т.к. не всегда знаешь (я-то знаю :) ) где они вызываются и как работают.

Следующим шагом сделаем копию виджета для вывода "развесованного" списка брендов. Для этого открываем файл view/View.php и добавляем сначала вызов метода - находим вызов

$this->design->smarty->registerPlugin("function", "get_brands", array($this, 'get_brands_plugin'));

И сразу после него добавляем наш расширенный вызов

$this->design->smarty->registerPlugin("function", "get_brands_cloud", array($this, 'get_brands_cloud_plugin'));

Теперь создадим сам метод. В этом же файле перед методом get_browsed_products вставим наш метод

public function get_brands_cloud_plugin($params, &$smarty)
{
    if(!isset($params['visible']))
        $params['visible'] = 1;
    if(!empty($params['var'])) {

        $min = 0; $max = 0;
        $steps = 5; //делаем 5 градаций веса
        
        if(!isset($params['steps']))
            $steps = max($steps, $params['steps']);        
        
        $brands = $this->brands->get_brands_weight($params);
        //вычисляем наибольшее и наименьшее значение
        foreach($brands AS $v) {
            if(!$max || $max < $v->count) $max = $v->count;
            if(!$min || $min > $v->count) $min = $v->count;
        } 
        $range = log($max + 1) - log($min + 1);
        if(!$range) $range = 1;
        //расставляем веса к каждому бренду
        foreach($brands AS $v)
            $v->weigth = round((log($v->count + 1) - log($min + 1)) * $steps / $range);

        $smarty->assign($params['var'], $brands);
    }
}

После обсуждений на форуме и экспериментов - алгоритм поменял на логарифмический. Теперь вес товара колеблется строго между 0 и значением $steps.

Теперь осталось вывести данные в шаблон. Открываем на файл шаблона design/[ваш_шаблон]/html/index.tpl и вместо стандартной конструкции

{get_brands var=all_brands}

вызываем модифицированную нами

{get_brands_cloud var=all_brands}
{if $all_brands}
<div id="all_brands">
    <h2>Все бренды:</h2>
    {foreach $all_brands as $b}	
        <a href="brands/{$b->url}" style="font-size: {math equation="round(12 + 3 * x)" x=$b->weigth}px">{$b->name}</a>
    {/foreach}
</div>
{/if}

А также если надо, то в Вашей переменной $b содержится количество товара по этому бренду, т.е. Вы можете использовать его в виде {$b->count} для вывода на сайте.

В переменной {$b->weigth} будет значение из интервала от 0 до 1 - коэффициент. Следовательно в выводе round(12 + 3 * x) мы получим значение от 12 до 25 при значении шага равным 5.

Вот что у меня получилось

Все файлы можно скачать по ссылке. Следующим шагом будем прикручивать флешевый вариант - веса-то у нас уже есть.

Удачной работы!

P.S. Изменил алгоритм расчета, спасибо помощи сообщества Yii.

Комментарии
Ваш отзыв будет первым