Group MySQL results into blocks of A-Z in PHP - php

I have a list of thousands of results and I want to group them alphanumerically for example, I need it to be like this:
<h1>0-9</h1>
<ul>
<li>011example</li>
<li>233example</li>
<li>65example</li>
</ul>
<h1>A</h1>
<ul>
<li>albert</li>
<li>alfred</li>
<li>annie</li>
</ul>
<h1>B</h1>
<ul>
<li>ben</li>
<li>bertie</li>
<li>burt</li>
</ul>
But I can't work out how to split or group my results into 0-9 and A-Z.
Currently I have:
<?php
$get_az = mysql_query("SELECT custom_22 FROM db_table1");
echo '<ul>';
while ($row = mysql_fetch_assoc($get_az)) {
$getfirstletter = substr($row['custom_22'], 0,1);
$name = $row['custom_22'];
echo '<h1>'.$getfirstletter.'</h1>';
echo '<li>'.$name.'</li>';
}
echo '</ul>';
?>

Order by the name and handle each letter one by one.
$get_az = mysql_query("SELECT custom_22 FROM db_table1 ORDER BY custom_22 ASC");
$current_first_letter = null;
while ($row = mysql_fetch_assoc($get_az)) {
$first_letter = strtolower(substr($row['custom_22'], 0, 1));
if (preg_match("/[0-9]/", $first_letter)) { // detect digits
$first_letter = "0-9";
}
if ($first_letter !== $current_first_letter) {
if ($current_first_letter !== null) {
echo '</ul>';
}
echo '<h1>' . $first_letter . '</h1>';
echo '<ul>';
}
$current_first_letter = $first_letter;
echo '<li>' . htmlentities($row['custom_22']) . '</li>';
}
if ($current_first_letter !== null) {
echo '</ul>';
}

I would do it this readable way:
$get_az = mysql_query('SELECT custom_22 FROM db_table1 ORDER BY custom_22');
$groups = array();
split results to groups
while ($row = mysql_fetch_assoc($get_az)) {
$firstLetter = strtolower(substr($row['custom_22'], 0, 1));
check for digits
if (is_numeric($firstLetter)) {
$firstLetter = '0-9';
}
if (isset($groups[$firstLetter]) === false) {
$groups[$firstLetter] = array();
}
$groups[$firstLetter][] = $row['custom_22'];
}
simply iterate over groups and echoes it
foreach ($groups as $h1 => $items) {
echo sprintf('<h1>%s</h1>', strtoupper(htmlspecialchars($h1)));
echo '<ul>';
foreach ($items as $item) {
echo sprintf('<li>%s</li>', htmlspecialchars($item));
}
echo '</ul>';
}

Related

alphabetising table data using arrays / if statements

I have some data that I'm looping through and alphabetizing using if statements. My code works but the problem is it seems like a very "long way around". I'd like to know if there's another approach that I'm missing that could make this much easier.
Here's my PHP:
// MY QUERY
$query1 = "SELECT `categoryid`, `categoryname`
FROM `my_table_category`
ORDER BY `my_table_category`.`categoryname` ASC";
$browse = mysql_query($query1) or die(mysql_error());
$browse_rows = array();
while($row = mysql_fetch_assoc($browse)){
$browse_rows[] = $row;
}
// HERE MY ARRAYS FOR THE ALPHABET
$list_a = array(); $list_b = array(); $list_c = array();
$list_d = array(); $list_e = array(); $list_f = array();
$list_g = array(); $list_h = array(); $list_i = array();
// etc...
// HERE IS WHERE I'M GRABBING THE CATEGORY NAMES BY THEIR FIRST LETTER
// AND ADDING THEM TO AN ARRAY
foreach($browse_rows as $row){
if($row['categoryname'][0] == 'A'){
$list_a[] = $row['categoryname'];
}elseif($row['categoryname'][0] == 'B'){
$list_b[] = $row['categoryname'];
}elseif($row['categoryname'][0] == 'C'){
$list_c[] = $row['categoryname'];
}elseif($row['categoryname'][0] == 'D'){
$list_d[] = $row['categoryname'];
}
} //etc...
Here is my HTML:
<!-- HERE IS HOW I DISPLAY MY DATA -->
<div id="topics_a">
<h2>A</h2>
<ul class="browse_list">
<?
foreach($list_a as $name){
if ($holdcat <> $name) {
$holdcat = $name; ?>
<li><a href="index.php?state="<? echo $template->State."#".$browse_row['categoryid'];?>><? echo $name; ?></a></li>
<? }} ?>
</ul>
</div>
<div id="topics_b">
<h2>B</h2>
<ul class="browse_list">
<?
foreach($list_b as $name){
if ($holdcat <> $name) {
$holdcat = $name; ?>
<li><a href="index.php?state="<? echo $template->State."#".$browse_row2['categoryid'];?>><? echo $name; ?></a></li>
<? }} ?>
</ul>
</div>
//etc...
Updated after the answer:
//UPDATED PHP
foreach ($browse_rows as $row) {
$initial = $row['categoryname'][0];
$lists[$initial][] = $row['categoryname'];
}
//UPDATED HTML
<? foreach ($lists as $letter => $list){ ?>
<div>
<h2><? echo $letter; ?></h2>
<ul class="browse_list">
<?
$list = array_unique($list);
foreach ($list as $cat) {
?>
<li><? echo $cat; ?></li>
<? } ?>
</ul>
</div>
<? } ?>
Output:
http://d.pr/i/bt68
Use a multidimensional array, not separate arrays for each letter.
$lists = array();
foreach ($browse_list as $row) {
$initial = $row['categoryname'][0];
if (!isset($row[$initial])) {
$lists[$initial] = array();
}
$lists[$initial][] = $row['categoryname'];
}
Then when you want to display it, sort the array by the keys, then use nested loops:
ksort($lists);
foreach ($lists as $list) {
echo '<ul class="browse_list">';
$list = array_unique($list); // get rid of duplicates
foreach ($list as $cat) {
echo '<li>' . $cat . '</li>';
}
echo '</ul>';
}

PHP - Drop down not showing all items in mysql

I am Trying to make a drop down menu, and list multiple items as well.
like for example:
here is my database:
if you see in that image you can see only one of the rows have a parent if i want multiple rows to have a parent of 'Far Far Away123' it only shows one of the items
<?php
function build_dropdown ($parent, $pages){
$items = "";
foreach($pages as $page){
// $items = "";
if($page['parent'] == $parent){
$items = $page;
} // END if
} // END foreach
if(is_array($items)){ // If a sub
echo '<ul id="sub_menu" class="sub_navagation'. $items['id'] .'">';
echo '<li>'.$items['page_name'].'</li>';
echo '</ul>';
} // END if
}// End Function
$sql = "SELECT * FROM pages ORDER by item_order";
$result = mysqli_query($db, $sql);
confirm_query($result);
while ($row = mysqli_fetch_assoc($result)) {
$pages[] = $row; // Add each row to $pages array to use later
}
foreach($pages as $key => $page){
if($page['parent'] == 'none'){ ?>
<li id = "<?php echo $page['id']; ?>">
<a href="page.php?id=<?php echo $page['id']; ?>" title="<?php echo $page['page_title']; ?>">
<?php echo $page['page_name']; ?>
</a>
<?php ?>
<?php
} // END if
build_dropdown($page['page_name'], $pages); // If there are child items then build them out
echo "</li> ";
} // END foreach
?>
Thanks
It is because you add only one.
You have a foreach searching all pages for subitems and remember only one of them for the latter if (is_array())
function build_dropdown($parent, $pages)
{
// item is an array
$items = array();
foreach($pages as $page) {
if ($page['parent'] == $parent) {
// add an element to the array
$items[] = $page;
} // END if
} // END foreach
if ($items) {
echo '<ul id="sub_menu" class="sub_navagation">';
foreach ($items as $item) {
echo '<li>'.$item['page_name'];
build_dropdown($item['page_name'], $pages);
echo '</li>';
} // END foreach
echo '</ul>';
} // END if
}// End Function
By the way, it would be better to start with the function giving build_dropdown($parent = 'none', $pages)
Try this inside your buildDropdown() function..
$items = array();
foreach($pages as $page)
{
if($page['parent'] == $parent)
{
$items[] = $page;
}
}
if (count($items) > 0)
{
echo '<ul id="sub_menu_'.$parent.'" class="sub_navagation">';
foreach($items as $item)
{
echo '<li>'.$item['page_name'].'</li>';
}
echo '</ul>';
}

Loop through mysqli results array once to get all information

I am querying the database for data, but in order to do what I need, I end up looping through that results array at least three times. How do I get all of the info I need out of the array without having to loop so many times? I need to get data from the array based on the results from the previous loops. The code below is the only way I could figure out in order to only query the database once.
$recordSQL = mysqli_query($link, $sqlString);
$resultMonths = array();
while($recordResult = mysqli_fetch_assoc($recordSQL)) $resultMonths[] = $recordResult['date'];
mysqli_data_seek($recordSQL, 0);
$uniqueMonths = array_unique($resultMonths);
foreach($uniqueMonths as $key => $date){
echo '</div><div class="current-month">'.translateDate($date, '').'</div>';
$resultCompanies = array();
while($companyResult = mysqli_fetch_assoc($recordSQL)){
if($companyResult['date'] == $date) $resultCompanies[] = $companyResult['company'];
}
mysqli_data_seek($recordSQL, 0);
$uniqueCompanies = array_unique($resultCompanies);
$oldco = '';
foreach($uniqueCompanies as $key => $company){
$x = 0;
while($typeResult = mysqli_fetch_assoc($recordSQL)){
if($typeResult['date'] == $date && $typeResult['company'] == $company){
if($oldco != $typeResult['company']){
if($x != 0) echo '</div>';
echo '<div class="company-record">'.$typeResult['name'].' - ';
}
if($x > 0) echo ', ';
echo translateID('Type', $typeResult['type']).'('.translateID('Section', $typeResult['section']).')';
$oldco = $typeResult['company'];
$x++;
}
}
echo '</div>';
mysqli_data_seek($recordSQL, 0);
}
}
FYI, you are actually looping N**3 times. Do it this way:
$month_company_rows = array();
while ($row = mysqli_fetch_assoc($recordSQL)) {
$month_company_rows[$row['date']][$row['company']][] = $row;
}
foreach ($month_company_rows as $date => $company_rows) {
echo '</div><div class="current-month">'.translateDate($date, '').'</div>';
foreach ($company_rows as $company => $rows) {
echo '<div class="company-record">'.$company.' - ';
foreach ($rows as $x => $row) {
if($x > 0) echo ', ';
echo translateID('Type', $row['type']).'('.translateID('Section', $row['section']).')';
}
echo '</div>';
}
}

php/mysql array or query with some values

Hello I have this query
$upit = "SELECT id from usluga";
$rezultat = mysql_query($upit);
while($red = mysql_fetch_object($rezultat))
{
echo "<li>{$red->id}</li>";
}
I want on exit to get this:
<li>1,2,3,4,5,6</li>
<li>7,8,9,10,11,12</li>
<li>13,14,15,16,17,18</li>
<li>19,20,21,22,23,24</li>
and so on..
Any help?
You can use the mod operator(%) or use array functions to achive this
$upit = "SELECT id from usluga";
$rezultat = mysql_query($upit);
while ($red=mysql_fetch_object ($rezultat)) {
$t[] = $red->id;
}
$chunks = array_chunk($t, 6);
foreach ($chunks as $chunk) {
echo "<li>" . join(",", $chunk) . "</li>";
}
try this..
$upit="SELECT id from usluga";
$rezultat=mysql_query($upit);
$i=0;
$liflag=0;
while ($red=mysql_fetch_assoc($rezultat))
{
if($i<6)
{
$liflag=1;
if($i==0)
{
echo "<li>$red->id";
$i++;
continue;
}
else
{
echo ",$red->id";
$i++;
continue;
}
}
else
{
echo ",$red->id</li>";
$i=0;
$liflag=0;
continue;
}
}
if($liflag==1)
{
echo "</li>";
}

Show first letter of a list once?

I have a list of directory name and need to get the first letter from each name and just display it once before the start of that lettered group ie;
what I have:
1
2
3
4
5
Aberdeen
Arundel
Aberyswith
Bath
Bristol
Brighton
Cardiff
coventry
what I would like:
#
1
2
3
4
5
A
Aberdeen
Arundel
Aberyswith
B
Bath
Bristol
Brighton
C
Cardiff
coventry
function htmlDirList($subdirs) {
global $z_self, $z_img_play, $z_img_lofi, $z_img_more, $z_admin,
$z_img_down, $z_img_new, $zc;
$now = time();
$diff = $zc['new_time']*60*60*24;
$num = 0;
$dir_list_len = $zc['dir_list_len'];
if ($zc['low']) { $dir_list_len -= 2; }
$html = "";
$checkbox = ($z_admin || ($zc['playlists'] && $zc['session_pls']));
/**/
$row = 0;
$items = sizeof($subdirs);
$cat_cols = "2";
$rows_in_col = ceil($items/$cat_cols);
if ($rows_in_col < $cat_cols) { $cat_cols = ceil($items/$rows_in_col); }
$col_width = round(100 / $cat_cols);
$html = "<table width='600'><tr>";
$i = 0;
/**/
foreach ($subdirs as $subdir => $opts) {
if ($row == 0) {
$class = ($cat_cols != ++$i) ? ' class="z_artistcols"' : '';
$html .= "<td $class valign='top' nowrap='nowrap' width='$col_width%'>";
}
/*$currentleter = substr($opts, 0 , 1);
if($lastletter != $currentleter){
echo $currentleter;
$lastletter = $currentleter;
}*/
if($alphabet != substr($opts,0,1)) {
echo strtoupper(substr($opts,0,1)); // add your html formatting too.
$alphabet = substr($opts,0,1);
}
$dir_len = $dir_list_len;
$dir = false;
$image = $opts['image'];
$new_beg = $new_end = "";
if (substr($subdir, -1) == "/") {
$dir = true;
$subdir = substr($subdir, 0, -1);
}
$path_raw = getURLencodedPath($subdir);
$href = "<a href='$path_raw";
if (!$dir) {
if ($zc['download'] && $zc['cmp_sel']) { $html .= "$href/.lp&l=8&m=9&c=0'>$z_img_down</a> "; }
if ($zc['play']) { $html .= "$href&l=8&m=0'>$z_img_play</a> "; }
if ($zc['low'] && ($zc['resample'] || $opts['lofi'])) { $html .= "$href&l=8&m=0&lf=true'>$z_img_lofi</a> "; }
if ($checkbox) { $html .= "<input type='checkbox' name='mp3s[]' value='$path_raw/.lp'/> "; }
$num++;
if ($zc['new_highlight'] && isset($opts['mtime']) && ($now - $opts['mtime'] < $diff)) {
$dir_len -= 5;
if ($z_img_new) {
$new_end = $z_img_new;
} else {
$new_beg = $zc['new_beg'];
$new_end = $zc['new_end'];
}
}
}
$title = formatTitle(basename($subdir));
if (strlen($title) > $dir_len) {
$ht = " title=\"$title.\"";
$title = substr($title,0,$dir_len).$opts['mtime']."...";
} else {
$ht = "";
}
if ($zc['dir_list_year']) {
$di = getDirInfo($subdir);
if (!empty($di['year'])) $title .= " (".$di['year'].")";
}
$html .= "$href'$ht>$new_beg$title$new_end</a><br />";
$row = ++$row % $rows_in_col;
if ($row == 0) { $html .= "</td>"; }
}
if ($row != 0) $html .= "</td>";
$html .= "</tr></table>";
$arr['num'] = $num;
$arr['list'] = $html;
return $arr;
}
I need help to get work.
The following will display the list of directories, beginning each group with a first letter as beginning of the group (see codepad for proof):
(this assumes $dirs is array containing the names)
$cur_let = null;
foreach ($dirs as $dir) {
if ($cur_let !== strtoupper(substr($dir,0,1))){
$cur_let = strtoupper(substr($dir,0,1));
echo $cur_let."\n";
}
echo $dir . "\n";
}
You just need to add some formatting on your own, suited to your needs.
Edit:
Version grouping under # sign entries that begin with a number, can look like that:
$cur_let = null;
foreach ($dirs as $dir) {
$first_let = (is_numeric(strtoupper(substr($dir,0,1))) ? '#' : strtoupper(substr($dir,0,1)));
if ($cur_let !== $first_let){
$cur_let = $first_let;
echo $cur_let."\n";
}
echo $dir . "\n";
}
Please see codepad as a proof.
Is this what you are looking for?
<?php
$places = array(
'Aberdeen',
'Arundel',
'Aberyswith',
'Bath',
'Bristol',
'Brighton',
'Cardiff',
'coventry'
);
$first_letter = $places[0][0];
foreach($places as $p)
{
if(strtolower($p[0])!=$first_letter)
{
echo "<b>" . strtoupper($p[0]) . "</b><br/>";
$first_letter = strtolower($p[0]);
}
echo $p . "<br/>";
}
?>
Prints:
A
Aberdeen
Arundel
Aberyswith
B
Bath
Bristol
Brighton
C
Cardiff
coventry
My approach would be to generate a second array that associates the first letter to the array of names that begin with that letter.
$dirs; // assumed this contains your array of names
$groupedDirs = array();
foreach ($dirs as $dir) {
$firstLetter = strtoupper($dir[0]);
$groupedDirs[$firstLetter][] = $dir;
}
Then, you can iterate on $groupedDirs to print out the list.
<?php foreach ($groupedDirs as $group => $dirs): ?>
<?php echo $group; ?>
<?php foreach ($dirs as $dir): ?>
<?php echo $dir; ?>
<?php endforeach; ?>
<?php endforeach; ?>
This allows for a clean separation between two separate tasks: figuring out what the groups are and, secondly, displaying the grouped list. By keeping these tasks separate, not only is the code for each one clearer, but you can reuse either part for different circumstances.
Use something like this, change it to output the HTML the way you want thouugh:
sort($subdirs);
$count = count($subdirs);
$lastLetter = '';
foreach($subdirs as $subdir => $opts){
if(substr($subdir,0,1) !== $lastLetter){
$lastLetter = substr($subdir,0,1);
echo '<br /><div style="font-weight: bold;">'.strtoupper($lastLetter).'</div>';
}
echo '<div>'.$subdir.'</div>';
}
EDIT
Just realized $subdir is associative, made the change above:

Categories