PHP – вложенный список, разбитый на четные столбцы (исправление и обновления)

У меня есть продолжение предыдущей темы / вопроса, которые, я надеюсь, могут быть решены относительно небольшими обновлениями для этого существующего кода. В другой теме / вопросе я в значительной степени решил необходимость вложенного неупорядоченного списка. Мне нужно, чтобы вложенный неупорядоченный список разбивался на столбцы на основе количества тем.

Например, если запрос базы данных привел к 6 темам, а пользователю было задано 2 столбца для макета, в каждом столбце будет три темы (и соответствующие новостные статьи ниже).

Например, если запрос базы данных привел к 24 темам, а пользователю было задано 4 столбца для макета, каждый столбец будет иметь 6 тем (и соответствующие новостные статьи ниже).

Итак, я надеялся решить три вопроса:

1.) Исправить проблему деления, полагаясь на количество категорий (неупорядоченный список разбит на столбцы по количеству тем)

2.) Измените PHP-код для запуска двух запросов: один, чтобы найти количество уникальных имен темы и один, чтобы найти количество общих элементов в списке

3.) Создайте дублированный набор PHP-кода, который работает, чтобы полагаться на количество новостей, а не на категории (неупорядоченный список разбит на столбцы на основе количества новостей)

Может ли кто-нибудь предоставить обновление или указать мне в правильном направлении? Очень признателен!

$columns = // user specified; $result = mysql_query("SELECT * FROM News"); $num_articles = 0; // $dataset will contain array( 'Topic1' => array('News 1', 'News2'), ... ) $dataset = array(); while($row = mysql_fetch_array($result)) { if (!$row['TopicID']) { $row['TopicName'] = 'Sort Me'; } $dataset[$row['TopicName']][] = $row['NewsID']; $num_articles++; } $num_topics = count($dataset); // naive topics to column allocation $topics_per_column = ceil($num_topics / $columns); $i = 0; // keeps track of number of topics printed $c = 1; // keeps track of columns printed foreach($dataset as $topic => $items){ if($i % $topics_per_columnn == 0){ if($i > 0){ echo '</ul></div>'; } echo '<div class="Columns' . $columns . 'Group' . $c . '"><ul>'; $c++; } echo '<li>' . $topic . '</li>'; // this lists the articles under this topic echo '<ul>'; foreach($items as $article){ echo '<li>' . $article . '</li>'; } echo '</ul>'; $i++; } if($i > 0){ // saw at least one topic, need to close the list. echo '</ul></div>'; } 

UPDATE 12/19/2011: разделение обработки данных с логикой вывода (для «Темы X для каждого варианта столбца»):

Привет Хакре: Я набросал структуру моего вывода, но я борюсь с ткачеством двух новых функций со старой обработкой данных. Должен ли код ниже работать?

 /* Data Handling */ $columns = // user specified; $result = mysql_query("SELECT * FROM News LEFT JOIN Topics on Topics.TopicID = New.FK_TopicID WHERE News.FK_UserID = $_SESSION[user_id] ORDER BY TopicSort, TopicName ASC, TopicSort, NewsTitle"); $num_articles = 0; // $dataset will contain array( 'Topic1' => array('News 1', 'News2'), ... ) $dataset = array(); while($row = mysql_fetch_array($result)) { if (!$row['TopicID']) { $row['TopicName'] = 'Sort Me'; } $dataset[$row['TopicName']][] = $row['NewsID']; $num_articles++; } /* Output Logic */ function render_list($title, array $entries) { echo '<ul><li>', $title, '<ul>'; foreach($entries as $entry) { echo '<li>', $entry['NewsID'], '</li>'; } echo '</ul></li></ul>; } function render_column(array $topics) { echo '<div class="column">'; foreach($topics as $topic) { render_list($topic['title'], $topic['entries']); } echo '</div>'; } 

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

Вы можете использовать функции агрегации в mysql для получения упорядоченных и сгруппированных записей новостей по темам, включая. их счет. Вы можете выполнить два запроса, чтобы получить счет сначала, это немного зависит от того, как вы хотите иметь дело с вашими данными.

В любом случае, используя функции mysql_... , все данные, которые вы выбрали из базы данных, будут в памяти (даже дважды из-за внутренних элементов). Таким образом, наличие другого массива, как в вашем предыдущем вопросе, не должно сильно повредить благодаря копированию на оптимизацию записи в PHP. Эффективно только небольшие накладные расходы.

Рядом с этим, прежде чем вы позаботитесь о фактическом выходе, вы должны упорядочить свои данные, чтобы вам не нужно было смешивать обработку данных и логику вывода. Смешивание делает вещи более сложными, поэтому их труднее решить. Например, если вы помещаете свой вывод в простые функции, это становится проще:

 function render_list($title, array $entries) { echo '<ul><li>', $title, '<ul>'; foreach($entries as $entry) { echo '<li>', $entry['NewsID'], '</li>'; } echo '</ul></li></ul>; } function render_column(array $topics) { echo '<div class="column">'; foreach($topics as $topic) { render_list($topic['title'], $topic['entries']); } echo '</div>'; } 

Это уже решает проблему вывода, поэтому нам больше не нужно заботиться об этом. Нам просто нужно заботиться о том, что нужно вводить в эти функции в качестве параметров.

Варианты X для каждого столбца:

В этом варианте данные должны быть массивом с одним типом за значение, как и с предыдущим вопросом. Я бы сказал, что это уже решено. Не знаю, какая конкретная проблема у вас есть с количеством столбцов, расчет выглядит хорошо, поэтому я пропущу это, пока вы не предоставите конкретную информацию об этом. «Не работает» не подходит.

X новостей в столбце:

Это более интересно. Здесь легко перейти к предыдущей теме в следующем столбце, добавив заголовок темы еще раз. Что-то вроде:

 Topic A Topic A Topic B - A-1 - A-5 - B-4 - A-2 Topic B - B-5 - A-3 - B-1 - B-6 - A-4 - B-2 - B-3 

Для этого вам нужно обрабатывать свои данные по-другому, а именно по количеству (новостям).

Допустим, вам удалось получить данные, сгруппированные (и, следовательно, отсортированные) из вашей базы данных:

 SELECT TopicName, NewsID FROM news GROUP BY 1; 

Затем вы можете просто перебрать все возвращенные строки и создать свои столбцы, наконец, вывести их (уже решены):

 $itemsPerColumn = 4; // get columns $topics = array(); $items = 0; $lastTopic = NULL; foreach ($rows as $row) { if ($lastTopic != $row['TopicName']) { $topic = array('title' => $row['TopicName']); $topics[] = &$topic; } $topic['entries'][] = $row; $items++; if ($items === $itemsPerColumn) { $columns[] = $topics; $topics = array(); $lastTopic = NULL; } } // output foreach($columns as $column) { render_column($column); } 

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

Опять же, это одно и то же: Итерация по возвращаемому набору результатов и перенос данных в структуру, которую вы можете выводить. Вход, обработка, вывод. Это всегда то же самое.

Надеюсь, это полезно.