Циклы и разбивка по колонкам

Еще одна полезность на заметку… Вот бывает вы получаете N количество записей и надо это набить в колонки. Здесь есть как минимум два варианта и есть в результатах тонкости. Заодно мы и рассмотрим применение кратности для выполнения этой задачи.

Рассмотрим два варианта.

Вариант 1.

$arr = array('Адлер', 'Александров', 'Анапа', 'Белгород', 'Галич', 'Гатчина', 'Елец', 'Дубна', 'Киров');
$cols = 2;
$count = count($arr);
$i = 1;
$output = "<ul>"; 
    foreach($arr as $a){
        $output .= "\n\t<li>{$a}</li>";
        if($i%$cols == '0' AND $i < $count){
            $output .= "\n</ul>\n<ul>";
        }
        $i++;
    }
$output .= "\n</ul>";
print $output;

Результат:

<ul>
	<li>Адлер</li>
	<li>Александров</li>
</ul>
<ul>
	<li>Анапа</li>
	<li>Белгород</li>
</ul>
<ul>
	<li>Галич</li>
	<li>Гатчина</li>
</ul>
<ul>
	<li>Елец</li>
	<li>Дубна</li>
</ul>
<ul>
	<li>Киров</li>
</ul>

Здесь самое главное — это проверка кратности индекса текущего элемента iиколичестваколонокi и количества колонок cols. Если поменяем кол-во колонок в переменной $cols, то получим и соответствующее количество колонок на выходе. В итоге мы получили по два города на строчку. Но здесь есть момент — города по порядку расположены горизонтально, что не есть удобно, так как удобней, когда порядок идет вертикально по колонкам. Посмотрим второй пример:

$arr = array('Адлер', 'Александров', 'Анапа', 'Белгород', 'Галич', 'Гатчина', 'Елец', 'Дубна', 'Киров');
$cols = 2;
$count = count($arr);
$i = 1;
$output = "<ul>";  
    foreach($arr as $a){
        $output .= "\n\t<li>{$a}</li>";
        if($i < $count AND $i%ceil($count/$cols) == '0'){
            $output .= "\n</ul>\n<ul>";
        }
        $i++;
    } 
$output .= "\n</ul>";
print $output;

Вот здесь уже результат такой:

<ul>
	<li>Адлер</li>
	<li>Александров</li>
	<li>Анапа</li>
	<li>Белгород</li>
	<li>Галич</li>
</ul>
<ul>
	<li>Гатчина</li>
	<li>Елец</li>
	<li>Дубна</li>
	<li>Киров</li>
</ul>

То есть у нас здесь четко две колоночки, в каждой из которых записей примерно поровну. (Визуальное оформление уже само собой на совести CSS).

Comments

В смарти можно использовать встроенные переменные цикла вместо $i. Вот пример:

{* этот шаблон выведет 0|1, 1|2, 2|3, ... и т.д. *}

{foreach $arr as $a name=foo}

    {$smarty.foreach.foo.index}|{$smarty.foreach.foo.iteration},

{/foreach}

Я к тому, что в данном случае меньше шансов совершить ошибку. Да и код более понятным становится )

function toCols($data, $cols = 2, $tpl = 'ul > li') {
  $tpl = array_map(function($item) {
    return trim($item);
  }, explode('>', $tpl));
  
  $result = array();
  while(count($data) > $cols) {
    array_push($result, array_splice($data, 0, $cols));
  }
  array_push($result, $data);
  
  return "<{$tpl[0]}>".implode("</{$tpl[0]}><{$tpl[0]}>", array_map(function($item) use ($tpl) {
    return "<{$tpl[1]}>".implode("</{$tpl[1]}><{$tpl[1]}>", $item)."</{$tpl[1]}>";
  }, $result))."</{$tpl[0]}>";
}

$arr = array('Адлер', 'Александров', 'Анапа', 'Белгород', 'Галич', 'Гатчина', 'Елец', 'Дубна', 'Киров');

echo toCols($arr, 2);

Вот такой вариант деления на колонки, только что придумал :-D

Что-то комментариелка испоганила мой год, повырезала некоторые части, но в общем идея ясна я думаю

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

Внизу форма донейта есть, можете ускорить появления функционала :) А так пока просто некогда.

Вариант Сергея очень лаконично выглядит, вот именно для таких задач смарти идеально подходит.