Форум пользователей Impera CMS
Impera CMS - отличный движок для лёгкого создания интернет магазина.
Обладает невероятным количеством функций, необходимых в онлайн торговле.

Следить
Главная
22:08
21 дек
#
?
написал:

Добрый день.

Хочу отсортировать блок "Бренды" по количеству товаров, у которых указан этот бренд.

Код шаблона:

<h2>Бренды</h2>
<div>
    {foreach $all_brands as $br}
        {inputValue from='br->brand_id' assign=id}
        {$checked = (isset($smarty.request.filter_brand.$id)) ? 'checked' : ''}
        <div class="checkbox">
            <label {(intval($br->products_count) == 0) ? 'class="text-muted"' : ""}>
                <input type="checkbox" name="filter_brand[{$id}]" value="{$checked}" {$checked} {(intval($br->products_count) > 0) ? "" : 'disabled="disabled"'}/>
                {$br->name}
                {if intval($br->products_count) > 0}
                    <small>({$br->products_count})</small>
                {/if}
            </label>
        </div>
    {/foreach}

Таким образом в шаблоне будет выведен список брендов, и рядом с каждым брендом в скобках будет указано количество товаров этого бренда.

В шаблоне:

  • массив брендов $all_brands;
  • один очередной бренд $br;
  • количество товаров этого бренда $br->products_count

Хочу отсортировать список foreach по количеству товаров бренда.

Что сделал: в файле objects\.def-models\ClientPage.php ориентировочно на 490 строку до строки

$this->smarty->assignByRef('brands_list', $this->brands);

добавил:

// сортировка брендов по убыванию товаров этого бренда
$sorted_brands_tree = $this->brands_tree;
foreach ($sorted_brands_tree as $key_id => $value_prop_list) {
    foreach ($value_prop_list as $key_prop_id => $value) {
        if ( $key_prop_id == 'products_count' ) {
            $products_count[$key_id] = $value;
        }
    }
}
array_multisort($products_count, SORT_DESC, $sorted_brands_tree);
$this->smarty->assignByRef('all_brands_sorted', $sorted_brands_tree);

И в шаблоне указал

{foreach $all_brands_sorted as $br}

1. Вопрос: как сделать лучше? Например, в smarty есть модификатор sortby, но конструкция

{foreach from=$all_brands|@sortby:"#products_count" as $br}

не работает. Может быть нужно записать её под другому?

2. Вопрос: как аккуратно то же сделать и со свойствами товаров? Если нельзя средствами смарти, то в каком файле задаётся переменная $properties, которая выводится в шаблоне template/products.htm, где можно её изменить в ядре движка?

Спасибо.

11:21
22 дек
#
написал:

Изменять код ядра - лишнее, так как создаст вам трудности при обновлении версии движка. Для целей выполнения собственного PHP-кода в момент, когда движок отработал и выполняется генерация страницы по шаблону, предусмотрена поддержка файла design/ИмяШаблона/html/helper.php.

По сути helper.php - это способ расширить шаблон вашими собственными функциями. Покажу простейший вариант использования хелпера, чтобы решить вашу задачу сортировки брендов.

Сначала пишем хелпер

Он содержит общедоступный метод sortBy для универсальной сортировки массива элементов по любому имени полю, а также передаёт себя под видом переменной $myHelper в шаблон, чтобы через эту переменную можно было вызвать любой из общедоступных методов хелпера.

<?php
    class TemplateEmulator {
        private $sortByFieldName;

        public function __construct ( & $cms ) {
            $cms->smarty->assignByRef('myHelper', $this);
        }

        private function compareBy ( $left, $right ) {
            $field = $this->sortByFieldName;
            if (!isset($left->$field)) return -1;
            if (!isset($right->$field)) return 1;
            if ($left->$field == $right->$field) return 0;
            return $left->$field < $right->$field ? -1 : 1;
        }

        public function sortBy ( & $items, $fieldName ) {
            $this->sortByFieldName = $fieldName;
            usort($items, array($this, 'compareBy'));
            return '';
        }
    }
?>

Особенности compareBy Строки if (!isset($...->$field)) return ...; могут быть удалены, так как служат страховочным целям, чтобы обслужить ситуацию, когда в шаблоне ошиблись и передали не массив объектов.

Особенности sortBy Это версия метода с возвратом результата во входной параметр, а не на выход метода. Последняя команда "возврат пустой строки" связана с особенностями работы Smarty - вывод результата на экран, если явно не присваивался какой-то переменной.

Теперь в шаблоне

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

{$myHelper->sortBy($all_brands, 'products_count')}

{foreach $all_brands as $br}
    ...
    ...
{/foreach}

Поясню особенности Smarty насчёт возврата результата

Для примера изменю последнюю команду метода.

<?php
    class TemplateEmulator {
        ...
        ...
        public function sortBy ( & $items, $fieldName ) {
            $this->sortByFieldName = $fieldName;
            usort($items, array($this, 'compareBy'));
            return 'Hello World';
        }
    }
?>

Тогда следующий код одновременно и отсортирует массив, и выведет на экране "Hello World", именно в месте вызова метода.

{$myHelper->sortBy($all_brands, 'products_count')}

Пример традиционной техники возврата результата

Метод изменён так, чтобы получили новый массив с сохранением старого.

<?php
    class TemplateEmulator {
        ...
        ...
        public function sortBy ( & $items, $fieldName ) {
            $this->sortByFieldName = $fieldName;
            $sorted = $items;
            usort($sorted, array($this, 'compareBy'));
            return $sorted;
        }
    }
?>

И в шаблоне:

{$all_brands_sorted = $myHelper->sortBy($all_brands, 'products_count')}

{foreach $all_brands_sorted as $br}
    ...
    ...
{/foreach}

Насчёт свойств

Принцип сортировки тот же самый, только скорректировать под структуру переменной $properties. Упомяну также о полезной отладочной функции, которая распечатывает на экране структуру конкретной переменной, если та является массивом или объектом. Для этого пишем в шаблоне так:

{dumpStructure from=properties}

Ещё примеры:

{dumpStructure from=all_brands}
{dumpStructure from=categories}
{dumpStructure from='category->path'}
{dumpStructure from=products}
{dumpStructure from='product->variants'}

И так далее. Распечатка не углубляется далее второго уровня вложенности. Позволяет быстро узнать, какие же поля есть в этой переменной и их тип.

18:11
06 янв
#
?
написал:
Разработчик написал: Принцип сортировки тот же самый, только скорректировать под структуру переменной $properties

Прошу подсказать, как скорректировать сортировку под структуру многомерного массива.

Структура вывода свойств такая:

{foreach $properties as $prop}
    {foreach $prop->options as $option}
        {$option->value} ({$option->count})
    {/foreach}
{/foreach}

Пробовал:

1. в функции сортировки писать так:

return $left['options']->$field < $right['options']->$field ? 1 : -1;

2. в шаблоне писать так:

{$emulator->sortBy($prop, 'count')}

или

{$emulator->sortByArr($prop, 'prop->count')}

3. и вот так:

{$emulator->sortBy($properties, 'properties->options->count')}

Функцию сортировки писал и до и после первого foreach.

18:27
06 янв
#
?
написал:

Также пробую вывести содержимое массива $Pages шаблона html/navigation.htm вот так:

{dumpStructure from=Pages}

но ничего не выводится. Почему такое может быть?

11:08
07 янв
#
?
написал:
Максим написал:скорректировать сортировку под структуру многомерного массива
{foreach $properties as $prop}
    {$emulator->sortBy($prop->options, 'count')}
    {foreach $prop->options as $option}
        {$option->value} ({$option->count})
    {/foreach}
{/foreach}
Максим написал:{dumpStructure from=Pages} но ничего не выводится

Потому что импера 100500 нюансов недокументированых. Код функции тут objects\.any-models\SmartyTags.php. Печатает объект или масив. $Pages масив строк.

Есть такое

<pre>{print_r($Pages)}</pre>
или
<pre>{var_dump($Pages)}</pre>

Есть еще

<pre>{$Pages|print_r}</pre>
<pre>{$Pages|var_dump}</pre>

Хз чем отличаются.

Написание ответа

Перед публикацией рекомендуется использовать Предпросмотр, чтобы увидеть конечный вид сообщения.


Обратите внимание! Для противодействия спаму новые посты форума проявляются с задержкой от нескольких минут, пока не пройдут модерацию.