groupIt - обертка результатов.


Была задача вывод элементов от pdoResources поделить на группы и обернуть их в div.
Поиск дал приятный результат, я нашел ответ в виде спиппета groupResources(это был обычный велосипед) и переписал его на свой лад.
Пример его работы
   <div class="group">
     ContentA
     ContentB
     ContentC
   </div>
   <div class="group">
     ContentD
     ContentE
   </div>


ilyautkin, помог мне еще раз переписать скрипт с использованием чанков.
Сниппет
<?php
    /**
     * groupIt
     *
     * AUTHOR
     *  DimenSi, но на самом деле ilyautkin разжевал.
     *  sergant, спасибо за советы.
     *
     * DESCRIPTION
     *
     * groupIt делит результат вывода pdoResources на группы блоков.
     *
     * PROPERTIES:
     *
     * &groupN на какое число делить, по-умолчанию 3.
     * &tplWrapper шаблон для обертки, по-умолчанию @INLINE <div>[[+wrapper]]</div>.
     *
     * [[groupIt? &groupN=`3` &tplWrapper=`@INLINE <div>[[+wrapper]]</div>` ]]
     */

    $tplWrapper = $modx->getOption('tplWrapper', $scriptProperties, '@INLINE <div>[[+wrapper]]</div>');
    $groupN     = $modx->getOption('groupN', $scriptProperties, 3);
    if (!isset($scriptProperties['outputSeparator'])) {
        $scriptProperties['outputSeparator'] = '||';
    }

    $rows     = $modx->runSnippet('pdoResources', $scriptProperties);
    $rows     = explode($scriptProperties['outputSeparator'], $rows);
    $groupped = array_chunk($rows, $groupN);

    $output   = array();
    $pdo = $modx->getService('pdoTools');
    foreach ($groupped as $group) {
        $wrapper  = implode(PHP_EOL, $group);
        $output[] = $pdo->getChunk($tplWrapper, array('wrapper' => $wrapper));
    }

    return implode(PHP_EOL, $output);

Я попробовал написать такой же сниппет сам. Вот, что получилось.
 <?php
    /**
     * groupIt
     *
     * AUTHOR
     * 
     * dimensi
     * 
     * DESCRIPTION
     *
     * groupIt делит результат вывода pdoResources на группы блоков.
     *
     * PROPERTIES:
     *
     * &wrapperOn вкл/выкл обертку, по-умолчанию 0
     * &wrapperTag тег обертки, по-умолчанию div
     * &wrapperClass класс обертки
     * &wrapperId id обертки
     * &groupN на какое число делить, по-умолчанию 3
     * &groupTag тег группы, по-умолчанию div
     * &groupClass класс группы
     * &snippet сниппет, по-умолчанию pdoResources
     *
     * USAGE:
     *
     * [[groupIt? &wrapper=`1` &wrapperClass=`Class` &wrapperId=`id` &wrapperTag=`div`
     * &groupN=`3` &groupTag=`div` &groupClass=`ClassGroup` &snippet=`pdoResources`]]
     */

    $wrapperOn       = $modx->getOption('wrapperOn', $scriptProperties, 0);
    $wrapperTag      = $modx->getOption('wrapperTag', $scriptProperties, 'div');
    $wrapper         = $wrapperTag;
    $wrapperClass    = $modx->getOption('wrapperClass', $scriptProperties);
    $wrapperId       = $modx->getOption('wrapperId', $scriptProperties);
    $groupN          = $modx->getOption('groupN', $scriptProperties, 3);
    $groupTag        = $modx->getOption('groupTag', $scriptProperties, 'div');
    $groupClass      = $modx->getOption('groupClass', $scriptProperties);
    $group           = $groupTag;
    $snippet         = $modx->getOption('snippet', $scriptProperties, 'pdoResources');
    $result          = '';

    if (!isset($scriptProperties['outputSeparator'])) {
        $scriptProperties['outputSeparator'] = '||';
    }
    $rows = $modx->runSnippet($snippet, $scriptProperties);
    $rows = explode($scriptProperties['outputSeparator'], $rows);

    if (isset($groupClass)) {
        $group = "{$groupTag} class='{$groupClass}'";
    }
    foreach ($rows as $i => $row) {
        $result .= $row;
        if (($i + 1) % $groupN == 0 && ($i + 1) !== count($rows)) {
            $result .= "</{$groupTag}>" . PHP_EOL . "<{$group}>";
        }
    }
    $result = "<{$group}>\n{$result}\n</{$groupTag}>";
    if ($wrapperOn == 1) {
        if (isset($wrapperTag)) {
            $wrapper = $wrapperTag;
        }
        if (isset($wrapperClass)) {
            $wrapper .= " class='{$wrapperClass}' ";
        }
        if (isset($wrapperId)) {
            $wrapper .= " id='{$wrapperId}' ";
        }
        $result = "<{$wrapper}>\n {$result} \n</{$wrapperTag}>";
    }
    return $result;

14 августа 2016, 11:00    DimenSi   G+  
28    880 +26

Комментарии (25)

  1. Здоров Александр 14 августа 2016, 11:05 # 0
    Однозначно полезная вещь, вопрос не вижу ни в коде где указать кол-во элементов, оборачиваемых в slide
    1. DimenSi 14 августа 2016, 11:07 # +1
      Дописал, перечитайте)
      1. Здоров Александр 14 августа 2016, 11:09 # 0
        спасибо на днях заюзаю, как раз кучка слайдеров завалялась с группировкий и не знал что с ними делать)
    2. Павел Гвоздь 14 августа 2016, 19:47 # 0
      В который раз замечаю такую несправедливую ситуацию: кол-во добавивших в избранное в разы больше, чем кол-во плюсанувших. Вот и в данном случае, пока я не поставил плюс было — 5 добавивших в избранное и 0 рейтинг. Отсюда у меня вопрос: добавив данное решение в избранное оно до сих пор не является для вас таким, за что автору можно поставить плюс?)
      1. Здоров Александр 14 августа 2016, 19:52 # +1
        Павел, к сожалению такая ситуация есть, я ка-кто протупил с плюсом, но исправился
        1. Игорь 14 августа 2016, 20:17 # 0
          Лично я добавил заметку в избранное, чтобы не потерять — возможно в будущем данное решение и понадобится. Не «плюсовал», это плохо?
          1. Павел Гвоздь 14 августа 2016, 20:35 # 0
            Не мне судить, плохо это или хорошо. Однако, это говорит о том, что такие люди неблагодарные. К примеру, в реальной жизни, если я что-то придумал и делюсь с человеком, а он это берёт и пользуется этим — мне приятно, однозначно. Хотя, если б он сказал спасибо, автору было бы приятнее, не находишь?
            Я не хочу спорить или доказывать что-то кому-то, поэтому кроме данного примера я больше никак не смогу повлиять на твоё, и мнение схожих с тобой в этом людей.
            1. Игорь 15 августа 2016, 00:23 # 0
              Это говорит только о том, что человек добавил себе заметку в закладку (избранное) и возможно никогда им не воспользуется. Поэтому называть за это людей «неблагодарными», на мой взгляд, явно «перебор».
              1. Сергей Шлоков 15 августа 2016, 09:06 # 0
                +1.
              2. Сергей Шлоков 15 августа 2016, 09:57 # 0
                Не мне судить, плохо это или хорошо. Однако, это говорит о том, что такие люди неблагодарные.
                Прикольно. Эти два предложения писал один и тот же человек? )) Павел, помню твои горячие споры про «благоДарю» и алкоголь. Ты идеалист. Но мир не черно-белый. Если человек не подходит под твое понимание добра и зла, это не значит что он плохой. Он просто другой. Тем более, что ты сам когда-то пришел к такому выводу.
                Для примера скажу. Я мог бы добавить эту заметку в закладки для того, чтобы не забыть идею и использовать её в будущем, если вдруг встанет такая задача. Но плюса я бы не поставил. Человек взял чужой сниппет, старый престарый, и выложил как своё решение. Для новичка неплохо. Но выглядит оно как решение практического задания на курсах PHP первого уровня.
                if ($scriptProperties['wrapper'] == 1) {
                    $output .= "\n<" . $scriptProperties['wrapperTag'] . " ";
                };
                 
                if (isset($scriptProperties['wrapperClass']) && $scriptProperties['wrapper'] == 1) {
                    $output .= "class='" . $scriptProperties['wrapperClass'] . "'";
                };
                 
                if ($scriptProperties['wrapper'] == 1) {
                    $output .= ">";
                };
                
                Для плюса нужно всё-таки что-то посерьёзнее. Уверен, автор может лучше. Тем более он знаком с pdoTools.

                П.С. Кстати, данную возможность можно было бы легко добавить в pdoTools. Достаточно добавить всего 2 параметра — groupLimit и tplGroup.

                В общем:
                1. Избранное — это как закладка в книге. Плюс/минус — это реакция на содержание. У них разная семантика.
                2. С этими рейтингами разработчики начинают путать этот ресурс с соц. сетями. Осталось только ввести тут «друзей» и лайкать друг друга за фото собачки.
                1. DimenSi 15 августа 2016, 10:06 # 0
                  Эм, господин. Я же написал, что сниппет не мой, а с автором связаться не смог. Я просто выложил решение, которое нагуглил, вы же читали, что я написал? Я написал, что решение не мое, почему вы говорите, что я выложил это от своего имени… Я с пхп на вы говорю, сам бы такое написать не смог. С pdoTools тем более не знаком. Что за грубости в мой адрес…
                  Насчет плюсов и закладок. Я лично сам не всегда ставлю плюс, потому, что забываю, а закладки иногда вообще не использую, хоть и добавил.
                  1. Сергей Шлоков 15 августа 2016, 10:27 # 0
                    Если в коде нет ни строчки вашего кода, то беру свои слова «выложил как свое решение» обратно. Но тогда тем более не понятно возмущение Павла отсутствием плюсов.
                    Что за грубости в мой адрес…
                    Где я произнёс хоть одно слово грубости? Я дискутирую с Павлом. Про автора упомянул 1 раз. И ничего плохого я не вижу в коде начинающего программиста. Лично я помню, что сам был таким. Просто заметил, что для плюса он пока слабоват. Уверен, что тот же Павел сможет его сократить минимум раза в 3.
                    1. DimenSi 15 августа 2016, 10:30 # 0
                      Про какого вы автора(меня или автора этого штуки) говорите? И откуда вы взяли, что автор знает pdoTools? Строчку с pdoResources, это я добавил. Ибо там автор использовал getResources.
          2. Сергей Шлоков 15 августа 2016, 17:33 # 0
            Собственный сниппет выглядит уже короче и серьёзнее. Я же говорил, что автор может лучше. )
            Но это ещё не предел. Если обратить внимание на любой сниппет pdoTools, то можно увидеть, что у них есть параметры tpl, в которых можно указать чанк или INLINE код. Что гораздо удобнее, чем указывать теги, классы, id и т.д. Таким образом, один параметр tpl заменяет несколько параметров. Как я уже писал выше, для данного сниппета достаточно 2 параметров. Или 3-х, если нужно указать сниппет получения результатов. Но так как в этом сообществе уже мало кто пользуется getResources, то и этот параметр можно опустить. Просто сразу вызывать pdoResources, но разумеется с проверкой его наличия.
            1. DimenSi 15 августа 2016, 18:30 # 0
              Ну, я так и сделал, по умолчанию у нас pdoResources. Сниппет еще раз переписан. К сожалению @INLINE, я не смогу реализовать. Я по-гуглил и оказывается, это довольно сложная тема этот @BILDINGs.
              github.com/goldsky/modx-chunk-methods
              1. Сергей Шлоков 15 августа 2016, 18:56 # 0
                Вот этот сниппет достоин плюса.
                Есть пара замечаний.
                Непонятна вот эта конструкция
                $outputSeparator = $modx->getOption('outputSeparator', $scriptProperties, PHP_EOL);
                if (!isset($scriptProperties['outputSeparator'])) {
                    $scriptProperties['outputSeparator'] = '||';
                }
                
                Представь, как будет выглядеть вывод, если вызвать сниппет с параметром &outputSeparator=`||`.
                Ну и второе. Ничего сложного с биндингом нет. Достаточно глянуть в документацию. Нужно добавить одну строчку и одну изменить.
                ...
                $pdoTools = $modx->getService('pdoTools');
                foreach ($groupped as $group) {
                   $wrapper  = implode(PHP_EOL, $group);
                   $output[] = $pdoTools->getChunk($tplWrapper, array('wrapper' => $wrapper));
                }
                
                Тогда шаблон можно указать в стиле pdoTools, к которому многие уже привыкли
                $tplWrapper = $modx->getOption('tplWrapper', $scriptProperties, '@INLINE <div class="group-wrapper">[[+wrapper]]</div>');
                

                П.С. Не увидел ни одного комментария Ильи. Видимо вы с ним телепатически общаетесь.
                1. Илья Уткин 15 августа 2016, 23:49 # 0
                  Конечно, телепатически. С опытом появляются экстрасенсорные способности — находить баги удалённо, исправлять неработающий функционал одним своим присутствием. =)))
                2. Сергей Шлоков 15 августа 2016, 19:03 # 0
                  По первому замечанию подскажу.
                  $outputSeparator вообще не нужен.
                  А $scriptProperties['outputSeparator'] присвоить значение без условий
                  $scriptProperties['outputSeparator'] = '||';
                  Ну и возврат делать так
                  return implode(PHP_EOL, $output);
                  1. DimenSi 15 августа 2016, 19:26 # 0
                    Ну изначально, я преследовал цель сделать и для pdoResources и getResources, но думаю, вы правы и нет смысла за таким гоняться, а просто сделать так, как в сообществе привыкли.
                    1. Илья Уткин 15 августа 2016, 23:47 # 0
                      По первому случаю согласен, а вот при возврате лучше подставить то, что нужно пользователю. Вдруг нужно группы вывести через запятую, например…
                3. Александр Москвин 16 августа 2016, 03:52 # 0
                  я обычно для таких случаев использовал стандартный функционал
                  [[pdoResources? &sortby=`menuindex` &tpl=`client_item` &tpl_n9=`client_item_row`]]
                  Работает, чуть помудрить с закрытием тегов и работает)
                  1. DimenSi 16 августа 2016, 11:41 # 0
                    Ну, это немного жесть…
                    1. Илья Уткин 16 августа 2016, 12:37 # +5
                      Не надо ничего мудрить. Даже отдельный шаблон не нужен. Я обычно так делаю:
                      <div>
                          [[pdoResources?
                            &parents=`0`
                            &limit=`0`
                            &tpl=`@INLINE <p>{$pagetitle}</p>{if $idx % 5 == 0}</div><div>{/if}`
                          ]]
                      </div>

                      Но тут человек хотел именно сам разобраться с тем, как писать сниппеты для MODX. Он получил большой опыт за небольшое время. Ну и далеко не все наткнутся где-нибудь на моё решение, а если это будет отдельный сниппет, начинающие будут им пользоваться.
                      1. DimenSi 16 августа 2016, 19:28 # 0
                        Оказывается способ решить проблему, был таким простым)
                        1. Александр Москвин 17 августа 2016, 01:56 # 0
                          забыл про включенный в pdoTools шаблонизатор, да так лучше, спасибо)
                          А опыт да, нужно иногда написать пару велосипедов, чтобы понять в чем суть)
                      Вы должны авторизоваться, чтобы оставлять комментарии.