Мне нужно создать таблицу HTML, которая показывает данные для пользователей по сравнению с посещенными страницами. Кажется нелепым использовать циклы for и / или foreach, но я не могу придумать ничего лучше. Я использую PHP, но предполагаю, что это не зависит от языка.






Что ж, если у вас есть несколько строк с одинаковым форматированием данных в каждой строке, я не могу придумать способ создать таблицу, которая бы избегала использования цикла. Именно для этого и были изобретены петли.
Если вы предоставите нам более подробную информацию о таблице, которую хотите построить, возможно, мы сможем сформулировать лучший метод.
Если вы не используете цикл типа немного, вам нужно жестко указать количество строк и столбцов в вашем коде, что, вероятно, намного хуже.
Если данные в таблице динамические, вам нужно использовать цикл. Даже если у вас есть компонент, который генерирует для вас таблицу, внутри он будет использовать цикл.
Это зависит от вашего определения «лучший». Циклы FOR отлично справятся с этой задачей. Я не программист PHP, но в .NET вы можете использовать Repeater, своего рода шаблон, который можно использовать для объявления таблицы HTML. У него есть шаблоны для верхнего колонтитула, нижнего колонтитула и каждого элемента. Вы привязываете источник данных к повторителю, и он сгенерирует для вас HTML-код таблицы немного более элегантно, чем использование циклов FOR. Я полагаю, что в PHP может быть какой-то эквивалент шаблонов.
В конце концов, даже Repeater использует какую-то петлю ...
Избежать циклов, вероятно, невозможно, если не в реализации, то это все равно произойдет на уровне машины.
Однако, если вы хотите попробовать оставаться «чистым» без неприятного кода, вы можете, по крайней мере, сделать:
$tableformat = '<table><thead>%s</thead><tbody>%s</tbody></table>';
$rowformat = '<tr>%s</tr>';
$cellformat = '<td>%s</td>';
$hdata = '';
foreach( $data[0] as $cellname => $cellvalue )
{
$hdata .= sprintf( $cellformat, $cellname );
}
$hdata = sprintf( $rowformat, $hdata );
$rdata = "";
foreach( $data as $rownum => $rowvalue )
{
$row = "";
foreach( $rowvalue as $colname => $colvalue )
{
$row .= sprintf( $cellformat, $colvalue );
}
$rdata .= sprintf($rowformat,$row);
}
return sprintf( $tableformat, $hdata, $rdata );
По крайней мере, так это могло быть в некоторой степени ремонтопригодным. и вас не беспокоят неполные строки.
Вы также можете заменить часть этого кода на
$hdata = "<tr><td>" . implode( "</td><td>", array_keys( $data[0] )) . "</td></tr>";
$rdata .= "<tr><td>" . implode( "</td><td>", $rowvalue ) . "</td></tr>";
Что, хотя и является довольно кратким, в конечном итоге, возможно, приведет вас к неприятностям и потребует перекодирования. (и внутреннее сжатие запускает цикл, так что это проигрыш).
Если вы не возражаете против лишних вызовов функций (и все еще работающих циклов), это может сделать код более кратким без слишком большого количества минусов:
$tableformat = '<table><thead>%s</thead><tbody>%s</tbody></table>';
$rowformat = '<tr>%s</tr>';
$cellformat = '<td>%s</td>';
function tr( $cells )
{
$o = "";
foreach( $cells as $i => $v )
{
$o .= sprintf( $cellformat, $v );
}
return sprintf( $rowformat, $o );
}
return sprintf( $tableformat,
tr( array_keys($data[0])),
implode("", array_map( 'tr', $data )) );
Но будьте осторожны, это трудно читать, и когда вы будете продолжать в том же духе, вы проснетесь с шепелявостью.
это искажает HTML в коде PHP, что (IMNSHO) даже хуже, чем искажение кода в HTML.
Не забудьте экранировать данные с помощью htmlspecialchars при встраивании их в HTML.
И ваш пример функционального стиля в конце не будет работать - PHP не имеет лексической области видимости.
От этого будет намного хуже! ;-)
Баггер. Для этого потребуется объект или глобальные переменные блевать. В 5.3 будут закрытия! .. но ... дрянная система пространств имён.
«Те, кто не знает Lisp, обречены изобретать его заново». Вы когда-нибудь видели «веб-библиотеку» Лиспа? они отбрасывают всю элегантность языка
Я настоятельно рекомендую шаблонизатор Умный для PHP. Это позволит вам переместить вашу таблицу (и связанный с ней цикл, что неизбежно) в шаблон, используя синтаксис Smarty, так что он будет более ясным и более отделенным от вашей бизнес-логики. Вы можете заменить почти весь код в своем примере несколькими простыми тегами в фрагменте HTML. Ознакомьтесь с ускоренным курсом на странице Smarty, чтобы увидеть пример использования таблицы.
Я обычно использую для этого циклы и implode в PHP. На языке, поддерживающем функциональное программирование, я бы поступил иначе.
function render_table($data) {
$html = '<table>';
$tr = array();
foreach (array_keys($data[0]) as $key) {
$tr[] = '<th>' . htmlspecialchars($key) . '</th>';
}
$html .= "\n" . '<thead>' . "\n" . '<tr>' . "\n" . implode("\n", $tr) . '</tr>' . '</thead>';
$tbody = array();
foreach ($data as $row) {
$tr = array();
foreach ($row as $value) {
$tr[] = '<td>' . htmlspecialchars($value) . '</td>';
}
$tbody[] = '<tr>' . "\n" . implode("\n", $tr) . '</tr>';
}
$html .= "\n" . '<tbody>' . "\n" . implode("\n", $tbody) . '</tbody>';
$html .= '</table>';
return $html;
}
Почему вы хотите избежать петель? Если у вас есть набор элементов, и вы хотите отобразить каждый элемент, очевидно, что цикл по набору является очевидным решением?
Если вы пытаетесь отделить модель от представления или написать более читаемый код, хорошо; но петли по своей сути не плохи.
Нет, неплохие. Но когда у вас большой набор данных и вы делаете с ним странные вещи, циклы не помогают сделать код читабельным.
Мне это очень нравится. Это делает код более аккуратным, чем циклы со случайными строками в них.