PHP -嵌套列表分成偶数列(修复和更新)


PHP - Nested List Broken into Even Columns (fix and updates)

我对之前的线程/问题进行了后续处理,我希望可以通过对该现有代码进行相对较小的更新来解决。在另一个线程/问题,我几乎解决了一个嵌套无序列表的需要。我需要将嵌套的无序列表根据主题的数量分解成列。

例如,如果一个数据库查询结果有6个主题,用户为布局指定了2列,那么每列将有3个主题(以及它下面的相关新闻项目)。

例如,如果一个数据库查询结果为24个主题,用户为布局指定了4列,那么每列将有6个主题(以及它下面的相关新闻项目)。

  • 上一个问题叫做PHP -简单嵌套无序列表(UL)数组。提供的解决方案工作得很好,但它并不总是分裂正确。例如,当$columns = 4时,它只除以列分成3组。代码如下:

  • 另一个我想解决的问题引起了我的注意回答问题的那位先生。而不是把所有内容都存入内存,然后第二次迭代打印它在这里,我想运行两个查询:一个查询查找的数量唯一的TopicNames和一个用于查找项目总数列表。

  • 我想解决的最后一件事是有一组重复的带有将嵌套无序列表分解为列的更新的代码基于新闻条目的数量(而不是类别)。所以,这可能只需要在这一秒交换几个变量

所以,我希望解决三个问题:

1)。修复依赖类别数量时的除法问题(根据主题数量将无序列表分解为列)

2)。重构PHP代码以运行两个查询:一个查找唯一topicname的数量,另一个查找列表

中项目的总数

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

2011年12月19日更新:将数据处理与输出逻辑分离(用于"每列变量的X个主题"):

Hi Hakre:我已经勾勒出了输出的结构,但是我正在努力将两个新函数与旧数据处理编织在一起。下面的代码应该工作吗?

/* 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);
}

因此,这实际上与上一个答案相当,但这次您不需要重新排列数组以获得按主题排序的新闻,因为数据库查询已经这样做了(您也可以对上一个答案这样做)。

还是一样的:对返回的结果集进行迭代,并将数据放入可以输出的结构中。输入,处理,输出。总是一样的。

希望对大家有帮助