PHP - a nested list, broken into even columns (bug fixes and updates)

I have a continuation of the previous question / question, which, I hope, can be resolved with relatively small updates for this existing code. In another topic / question, I pretty much decided the need for a nested unordered list. I need a nested unordered list to be columned based on the number of topics.

For example, if a database query resulted in 6 topics, and two columns were specified for the layout, each column will have 3 topics (and the corresponding news articles below).

For example, if a database query resulted in 24 topics and the user was given 4 columns for the layout, each column will have 6 topics (and the corresponding news articles below).

So, I was hoping to solve three questions:

1.) Fix the separation problem by relying on the number of categories (the unordered list is divided into columns based on the number of topics)

2.) Modify the PHP code to run two queries: one to find the number of unique topic names and one to find the number of common elements in the list

3.) Create a duplicate set of PHP code that works to rely on the number of news items, not categories (unordered list is divided into columns based on the number of news items)

Can someone provide an update or point me in the right direction? Really appreciate!

$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: Separation of data processing from output logic (for "Theme X for each column option"):

Hi Hakre: I sketched the structure of my output, but I am struggling with the fabric of two new functions with the old data processing. Should the code below work?

 /* 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>'; } 
0
source share
1 answer

You did not indicate in your two questions what a database table is, so I cannot answer it specifically, but we will present our proposal.

You can use the aggregation functions in mysql to get ordered and ordered news items by topic, including. their score. You can execute two requests to get an invoice first, it depends a little on how you want to process your data.

In any case, using the mysql_... functions, all the data you select from the database will be in memory (even twice due to internal elements). Thus, the presence of another array, as in your previous question, should not hurt much due to copying to write optimization in PHP. Only small overheads are effective.

Next to the fact that before you take care of the actual output, you must organize your data so that you do not need to mix data processing and output logic. Blending makes things more complicated, making them harder to solve. For example, if you put your output in simple functions, it becomes easier:

 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>'; } 

This already solves the output problem, so we no longer need to worry about that. We just need to take care of what to serve in these functions as parameters.

X options for each column:

In this option, the data should be an array with one type per value, as with the previous question. I would say that this has already been decided. I don’t know what specific problem you have with the number of columns, the calculation looks good, so I will skip this until you provide specific information about it. "Not working" does not fit.

X news column option:

This is more interesting. It’s easy to jump to the previous topic in the next column by adding the topic title again. Sort of:

 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 

To do this, you need to process your data in a different way, namely in terms of quantity (news).

Let's say you managed to get the data grouped (and therefore sorted) from your database:

 SELECT TopicName, NewsID FROM news GROUP BY 1; 

Then you can simply iterate over all returned rows and create your own columns, finally output them (already resolved):

 $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); } 

Thus, this is actually comparable to the previous answer, but this time you do not need to reconfigure the array to receive news ordered by their topic, because the database query does this already (you could do this for the previous answer as well).

Then again the same thing: Iterating over the returned result set and transferring the data to a structure that you can output. Input, processing, output. It is always the same.

Hope this will be helpful.

+1
source

Source: https://habr.com/ru/post/1341736/


All Articles