sql >> Base de Datos >  >> RDS >> Mysql

PHP - Matriz de lista desordenada anidada simple (UL)

Esto debería funcionar:

$result = mysql_query("SELECT * FROM News");
$topicname = '';

// open list of topics
echo '<ul>';

// loop through topics
while($row = mysql_fetch_array($result)) {
    if (!$row['TopicID']) {
        // fake topic name for unsorted stuff
        $row['TopicName'] = 'Sort Me';
    }
    if ($topicname != $row['TopicName']) {
        if($topicname != ''){
            // had a topic name, means we opened a list
            // that hasn't been closed, close it.
            echo '</ul>';
        }
        // print this topic and open the list of articles
        echo '<li>' . $row['TopicName'] . '</li><ul>';
        // update the current topic to be this TopicName
        $topicname = $row['TopicName']; 
    }
    // the news item
    echo '<li>' . $row['NewsID'] . '"</li>';
}
if($topicname != ''){
    // we saw at least one TopicName, we need to close
    // the last open list.
    echo '</ul>';
}
// end topic list
echo '</ul>';

Creo que su verdadero problema es que abría dos listas cada vez, pero solo cerraba una (incluso movía el último bloque dentro de la lista).

Para la segunda parte de su (nueva) pregunta:

Advertiré que para listas más grandes (digamos, más de 300 elementos), la compensación que estoy haciendo con respecto al almacenamiento de la lista en la memoria y la iteración dos veces en lugar de solo consultar los recuentos necesarios cambiaría en sentido contrario. Es decir, la solución a continuación pone todo en la memoria, luego itera por segunda vez para imprimirlo; una alternativa sería ejecutar dos consultas, una para encontrar la cantidad de TopicNames únicos y otra para encontrar la cantidad total de elementos en la lista.

Además, para la visualización, realmente desea resolver alguna optimización para el diseño, lo haré de manera ingenua y simplemente crearé una cantidad (aproximadamente) igual de temas por columna y cuando la división no funcione, esto pesará hacia la izquierda. Verá dónde puede modificar o reemplazar algún código para obtener resultados diferentes (¿y mejores?).

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