I have a "student" table, having around 5,000 records, in my DB. I want to display those records in two divs. How do I do that without executing the query twice; only using a single query?
display example http://www.freeimagehosting.net/uploads/f1c6bb41eb.gif
Just use CSS3. Not sure how widely it is supported but saves a lot of headache and is a lot more powerful when making changes.
Use column-count, and column-width to control the number of columns and width of each column. Here's some sample code and some pretty impressive results. Prefix -webkit and -moz for now until its standardized across all browsers.
.multi-column {
/* Standard */
column-count: 2;
column-width: 150px;
/* Webkit-based */
-webkit-column-count: 2;
-webkit-column-width: 150px;
/* Gecko-based */
-moz-column-count: 2;
-moz-column-width: 150px;
}
Applied to this <div>
<div class="multi-column">
Ethelred of Wessex
Louis XII of France
George Frideric Handel
George Washington
Charles Deslandes
Andrew Jackson
Alfred Vail
William McKinley
Woodrow Wilson
Abdul-Aziz ibn Saud
Fidel Castro
Charles de Gaulle
Leonardo da Vinci
</div>
Don't you wanna see how it looks like after all this hard work?
But what if there were 3 columns? No problem.
But there's no way it can handle 4 columns you'd say:
Enough! I gotta stop adding these now
God please make it STOP!!
Just find where the "middle" is and output the end tag of the div tag and the start tag of the second div:
<?
$rowcount = mysql_num_rows($recordset);
echo "<div id='div1'>";
$i = 0;
while ($d = mysql_fetch_object($recordset)) {
echo $d->somefield;
$i++;
if ($i == floor($rowcount / 2)) {
//we have reached the mid-point, let's close the first DIV
echo "</div><div id='div2'>";
}
}
echo "</div>";
?>
get_column() function could help, it will calculate column for each item you want to show.
this sample script show how to print in two columns, but you can change it in two minutes to fix your needs if you need other number of columns.
<?php
// sample query, get members
$query = mysql_query("select name from persons");
// count total number of items to show
$total = mysql_num_rows($query);
// initiate row counter
$counter = 1;
// initiate columns contents
$column_1 = '';
$column_2 = '';
while($row = mysql_fetch_assoc($query)){
// caluculate column for current element from total items to be showed number of columns and current item
$column = get_column($total, 2, $counter);
if($column == 1){
$column_1 .= $row['name'].'<br>';
}
if($column == 2){
$column_2 .= $row['name'].'<br>';
}
$counter++;
}
// show content in two table comments
echo "<table>
<tr>
<td>$column_1</td>
<td>$column_2</td>
</tr>
</table>";
?>
and the function is:
<?php
/**
* Calculate column number where an item should be displayed on a "newspaper style"
* or "phoneguide style" report according its postion
* used to put same number of items on each column
*
* receive 3 numbers: $vp_total_size: total number of items on report
* $vp_columns : number of columns of report
* $vp_element : element position for item (1 to $vp_total_size)
*
* by Marcos A. Botta <marcos DOT botta AT gmail DOT com>
* 02/02/2007
*
*/
function get_column($vp_total_size, $vp_columns, $vp_element){
if($vp_element <= 0){
return 1;
}
if($vp_element < $vp_columns &&
$vp_columns >= $vp_total_size){
return $vp_element;
}
$vl_avg_items_by_column = $vp_total_size / $vp_columns;
$vl_items_on_first_columns = ceil($vl_avg_items_by_column);
$vl_items_on_last_columns = floor($vl_avg_items_by_column);
$vl_column_limit = ($vl_avg_items_by_column - $vl_items_on_last_columns) * $vp_columns;
$vl_allocated_items = 0;
for($i=1;$i<$vp_columns;$i++){
if($i < $vl_column_limit ||
"$i" == "$vl_column_limit"){
$vl_items_on_current_column = $vl_items_on_first_columns;
}
else{
$vl_items_on_current_column = $vl_items_on_last_columns;
}
$vl_allocated_items += $vl_items_on_current_column;
if($vp_element <= $vl_allocated_items){
return $i;
}
}
return $vp_columns;
} // get_column()
?>
good luck!
My implementation:
<?php
$students = array(1,2,3,4,5);
$split = floor(count($students)/2);
echo '<div id="parent"><div id="col-1">';
$i = 0;
foreach($students as $student)
{
echo 'Student #' . $student . '<br />';
if($i == $split)
{
echo '</div><div id="col-2">';
}
$i++;
}
echo '</div></div>';
Using the CSS3 Webkit/Moz only features are in my opinion very bad practice.
Why dont you try this code, its simple using only css, easy to understand, working in ie and mozilla...
<style type="text/css">
.ulcol
{
float: left;
width: 400px;
margin: 0;
padding: 0;
list-style: none;
}
.licol
{
float: left;
width: 200px; /*half width of the ulcol width*/
margin: 0;
padding: 0;
}
</style>
<?php
$query = mysql_query("select * from table_name") or die("Error Occured,check again");
echo '<ul class="ulcol">';
while($row = mysql_fetch_assoc($query))
{
$vartitle = $row[db_row_title];
echo '<li class="licol">';
echo $vartitle
echo '</li>';
}
echo '</ul>';
?>
Maybe split the array into two then implode them and then print both halves on each div.
I prefer to minimize any early use of "echo", because tomorrow you will want to move this in a function or a method, where "echo" should be avoided. Moreover, with the "echo" in the loop you've lost the array structure inherent to databases, and you need this structure to manipulate your data. So I would rather fill an array, process it, then implode to output.
And I would use styled bullet points to display the items, because you apparently want to display a list of items. In pseudo php code:
while row = fetch(sql)
lines[] = "<li>row_data</li>"
end
// work on the lines array, eg insert "</ul><ul>" in the middle
echo "<ul>".implode("\n",lines)."</ul>"
Try something like this
// connection goes there
$q = "SELECT `name` FROM students";
$result = mysql_query($q);
$students = array();
while($row=mysql_fetch_assoc($result)) {
$students[] = $row['name'];
}
$students_count = sizeof($students);
// chunkes into a two parts , want more columns ? just change "2" to other number
$students_chuncked = array_chunk($students,ceil($students_count/2),true);
//now display
foreach ($students_chuncked as $student_div_data){
echo '<div>',explode($student_div_data,'<br/>'),'</div>';
}
Related
I'm having problems getting my PHP file to function properly. It is supposed to display a two-columned table containing departments (unordered list) and department categories (ordered list beneath each department).
The result at the moment is that the SECOND column is appearing perfectly fine, with the bulleted unordered list and numbered ordered lists beneath each bulleted department. The FIRST column, however, is being displayed WITHOUT any bullets or numbers. The data is there, but not in the format (ul and ol) that I was expecting.
Thanks for you help. Let me know if you need more information.
<?php
//displayDepartments.php
$query = "SELECT * FROM product_categories_reference
ORDER BY department_name DESC";
$category = mysql_query($query)
or die(mysql_error());
$numRecords = mysql_num_rows($category);
$catCount = 0;
$currentDepartment = "";
echo "<table><tr><td><ul>";
for ($i = 0; $i < $numRecords; $i++)
{
$row = mysql_fetch_array($category);
if ($currentDepartment != $row["department_name"])
{
if ($currentDepartment != "") echo "</ol></li>";
if ($catCount > $numRecords/2)
{
echo "</ul></td><td valign='top'><ul>";
$catCount = 0;
}
$currentDepartment = $row["department_name"];
echo "<li>$currentDepartment<ol>";
}
echo "<li><a href=\"category.php?cat='"
.$row["product_category_code"] . "'\">"
.$row["product_category_description"]
."</a></li>";
$catCount++;
}
echo "</ol></li></ul></td></tr></table>";
?>
You haven't provided css or a link, so this is a guess.
I'm assuming your css has a list-style-type set to none.
Change it to
ul {
list-style-type: disc;
}
I have this statement that works fine, but list alphabetical from left to right across 3 columns. I want it to list alphabetical vertically down the column and then continue onto the next column. Anyone know how I can do this.
$models = mysql_query("SELECT model, id FROM model where make='$phonemake' order by model asc") or die(mysql_error());
$count = 0;
$max = 3;
while($model = mysql_fetch_array( $models ))
{
$count++;
echo "<div style='float:left; width:31%; padding-right:5px;'>".$model['model']." <a href='include/delete-model.php?id=".$model['id']."' onclick='return makesure".$model['id']."();'>Delete</a></div>";
if($count >= $max){
//reset counter
$count = 0;
//end and restart
echo"<div style='clear:both;'></div>";
You have two options:
You can buffer result into array and change the order of adding of divs
The code could look like this:
$allmodels = array();
while($model = mysql_fetch_array( $models ))
{
$allmodels[] = $model;
}
for($i = 0; 3 * $i < count($allmodels); $i++)
{
for($j = 0; $j < 3; $j++)
{
if(isset($allmodels[($i * 3) + $j]))
{
$model = $allmodels[($i * 3) + $j];
// print your stuff here...
}
}
}
Or you can somehow reorder items in the sql query, maybe dump that to the temporary table or play with mysql_data_seek.
echo the data in a UL LIST , and use your counter to set the number of rows in the UL LIST , when counter is reaches max, create a new list and continue displaying. Personally i would use:
if($counter%3==0) {
create new list
}
this way you dont need to reset the counter everytime.
I'm trying to get a value to be inserted into a table on a webpage if the value equals $i.
$i starts at a number and decreases every loop. i can get it to work but it outputs multiple lines for each $i equivalent to the results in the table
I've reworked the code using everyones feedback to get this.
Echo "<tr><th colspan='3'><center>$rackname</th> </tr>" ;
for ($i=$RUtotal; $i > 0; $i--)
{
echo" <tr class='rackbg'><td class='i'><center>$i</td>" ;
$sql1 = "SELECT racks.rackID, racks.rackname, devices.deviceID, devices.deviceName, racks.rackRU, devices.deviceRU, devices.RUcount
FROM racks LEFT JOIN devices ON racks.rackID = devices.rackID
WHERE devices.rackID = '$rackID'";
$query1 = mysql_query($sql1);
while ($row = mysql_fetch_assoc($query1))
{
$deviceru = $row['deviceRU'];
$deviceID = $row['deviceID'];
$device = $row['deviceName'];
$deviceRUC = $row['RUcount'];
if ($deviceru == $i)
{
echo '<td class="device" rowspan='.$deviceRUC.'><a onclick=window.location="/devices.php?id='.$deviceID.'">'.$device.'</a></td><td rowspan='.$deviceRUC.'></td></tr>';
}
else
{
;
}
}
}
Echo "<tr class='rackb'><th colspan='3'>a</th></tr> " ;
This works to a degree (picture1) but when i add echo "" to the else statement it displays all wrong. (picture 2)
Any help would be greatly appreciated
Picture1 - http://imageshack.us/photo/my-images/263/examplewq.png/
Picture2 - http://imageshack.us/photo/my-images/269/example2jp.png/
I can't quite see what you're trying to do but what it looks like to me is that you want all the items from racks joined with their relevant device and displayed in order of deviceRU. Does this help:
echo "<tr><th colspan='3'><center><b>$rackname</th></tr>" ;
$sql1 = "SELECT racks.rackID, racks.rackname, devices.deviceID, devices.deviceName, racks.rackRU, devices.deviceRU, devices.RUcount
FROM racks LEFT JOIN devices ON racks.rackID = devices.rackID
WHERE racks.rackID = '$rackID' AND devices.deviceRU <= ".intval($RUtotal)."
ORDER BY devices.deviceRU;"
$query1 = mysql_query($sql1);
while ($row = mysql_fetch_array($query1))
{
$deviceru = $row['deviceRU'];
$deviceID = $row['deviceID'];
$device = $row['deviceName'];
$deviceRUC = $row['RUcount'];
echo'<tr class="rackbg"><td class="i">'.$i.'</td><td class="device">'.$device.'</td><td></td></tr>';
}
I've used a LEFT (inner) JOIN in the SQL instead of the outer join that was there before as it'll return less results and might solve your problem. I've ordered the results by deviceRU and only returned results which have deviceRU less than or equal to $RUtotal (as I think the example was showing).
I've also removed the tags, these should be replaced by using CSS to centre either all td elements or centering class="device" and class="i" e.g.:
.device, .i {
text-align: center;
}
I've also swapped your abc to abc which is the correct format for a link.
Could you describe more of the context as it's difficult to see your intention from your post.
Mat
As Peetz said, you don't need nested loop. You need something like:
$i = $RUtotal;
// ...
while ($row = mysql_fetch_array($query1)) {
// ...
if ($deviceru == $i) {
// ...
} else {
// ...
}
// ...
$i--;
}
This is looping $i times, within the outer while loop. This means you are getting the table repeated over and over again.
I suggest you remove the outer while loop.
I have a while loop that displays result from a MySQL query. I know how to change the output for the last row or an odd row but how can I change the output for the last two results?
For example I have a list of results in a 2x2 matrix with border-bottom: 1px on each result but I would like to display the bottom two without the border?
If you can use css3, it´s easy (I´ll use a list for the example):
li:nth-last-child(-n+2)
selects the last two li's.
If you want to do it in php, you can count the number of results, add a counter in your loop and add a class to the last two items.
Yeah just do it like this:
$result = //execute your query
$num_rows = mysql_num_rows($result;
$num_rows_different = 2;
$loop_counter = 0;
while ($loop_counter < $num_rows) {
if ($loop_counter < $num_rows - $num_rows_different) {
// with border
} else {
// no border
}
$loop_counter++;
}
I wouldn't use the CSS3 method due to its poor support...
I like the CSS way, but you'll need to know the total number of items you're listing. Then you can use a simple condition to check for that.
$total_items = [count of items];
$cnt = 0;
while($fetch as $row) {
...
if(++$cnt > ($total_items - 2)) {
// list with no border
} else {
// list with border
}
}
Have a webpage that will be viewed by mainly IE users, so CSS3 is out of the question.
I want it to list like:
A D G
B E H
C F I
Here is the function that currently lists like:
A B C
D E F
G H I
function listPhoneExtensions($group,$group_title) {
$adldap = new adLDAP();
$group_membership = $adldap->group_members(strtoupper($group),FALSE);
sort($group_membership);
print "
<a name=\"".strtolower($group_title)."\"></a>
<h2>".$group_title."</h2>
<ul class=\"phone-extensions\">";
foreach ($group_membership as $i => $username) {
$userinfo = $adldap->user_info($username, array("givenname","sn","telephonenumber"));
$displayname = "<span class=\"name\">".substr($userinfo[0]["sn"][0],0,9).", ".substr($userinfo[0]["givenname"][0],0,9)."</span><span class=\"ext\">".$userinfo[0]["telephonenumber"][0]."</span>";
if($userinfo[0]["sn"][0] != "" && $userinfo[0]["givenname"][0] != "" && $userinfo[0]["telephonenumber"][0] != "") {
print "<li>".$displayname."</li>";
}
}
print "</ul><p class=\"clear-both\">↑ top</p>";
}
Example rendered html:
<ul class="phone-extensions">
<li><span class="name">Barry Bonds</span><span class="ext">8281</span></li>
<li><span class="name">Gerald Clark</span><span class="ext">8211</span></li>
<li><span class="name">Juan Dixon</span><span class="ext">8282</span></li>
<li><span class="name">Omar Ebbs</span><span class="ext">8252</span></li>
<li><span class="name">Freddie Flank</span><span class="ext">2281</span></li>
<li><span class="name">Jerry Gilmore</span><span class="ext">4231</span></li>
<li><span class="name">Kim Moore</span><span class="ext">5767</span></li>
<li><span class="name">Barry Bonds</span><span class="ext">8281</span></li>
<li><span class="name">Gerald Clark</span><span class="ext">8211</span></li>
<li><span class="name">Juan Dixon</span><span class="ext">8282</span></li>
<li><span class="name">Omar Ebbs</span><span class="ext">8252</span></li>
<li><span class="name">Freddie Flank</span><span class="ext">2281</span></li>
<li><span class="name">Jerry Gilmore</span><span class="ext">4231</span></li>
<li><span class="name">Kim Moore</span><span class="ext">5767</span></li>
<li><span class="name">Barry Bonds</span><span class="ext">8281</span></li>
<li><span class="name">Gerald Clark</span><span class="ext">8211</span></li>
<li><span class="name">Juan Dixon</span><span class="ext">8282</span></li>
<li><span class="name">Omar Ebbs</span><span class="ext">8252</span></li>
<li><span class="name">Freddie Flank</span><span class="ext">2281</span></li>
<li><span class="name">Jerry Gilmore</span><span class="ext">4231</span></li>
<li><span class="name">Kim Moore</span><span class="ext">5767</span></li>
</ul>
Any help is appreciated to getting it to list alpha vertically.
I would load the critical data into an array so you can count them and step through them in whatever order you want. Then use an algorithm like this to get them in the right order:
$items = BuildItemArray(); // Get the values into an array.
$columnCount = 5;
$itemCount = count($items);
$rowCount = ceil($itemCount / $columnCount);
for ($i = 0; $i < $rowCount * $columnCount; $i++)
{
$index = ($i % $columnCount) * $rowCount + floor($i / $columnCount);
if ($index < $itemCount)
{
DisplayItem($items[$index]);
}
else
{
DisplayBlank();
}
}
I think that should work, but I haven't tested it.
I am posting my answer to this old question for the following reasons:
My answer is more general and easy for others to adapt.
I didn't want an overly complex solution.
My array was associative, with a string key. BTW, my solution will work for both associative and indexed arrays.
Actually, the solution I came up with was pretty simple--use multiple tags with style="float:left", inside of a giant table. While I was sceptical that having multiple tbody tags in a single table would pass HTML validation, it in fact did pass without errors.
Note the following
$numCols is your desired number of columns.
Since we are floating items, you may need to set the width and min-width of parent elements and/or add some <br style="clear: both" />, based on your situation.
for alternative sorting methods, see http://php.net/manual/en/array.sorting.php
Here's my full answer:
function sortVertically( $data = array() )
{
/* PREPARE data for printing */
ksort( $data ); // Sort array by key.
$numCols = 5; // Desired number of columns
$numCells = is_array($data) ? count($data) : 1 ;
$numRows = ceil($numCells / $numCols);
$extraCells = $numCells % $numCols; // Store num of tbody's with extra cell
$i = 0; // iterator
$cCell = 0; // num of Cells printed
$output = NULL; // initialize
/* START table printing */
$output .= '<div>';
$output .= '<table>';
foreach( $data as $key => $value )
{
if( $i % $numRows === 0 ) // Start a new tbody
{
if( $i !== 0 ) // Close prev tbody
{
$extraCells--;
if ($extraCells === 0 )
{
$numRows--; // No more tbody's with an extra cell
$extraCells--; // Avoid re-reducing numRows
}
$output .= '</tbody>';
}
$output .= '<tbody style="float: left;">';
$i = 0; // Reset iterator to 0
}
$output .= '<tr>';
$output .= '<th>'.$key.'</th>';
$output .= '<td>'.$value.'</td>';
$output .= '</tr>';
$cCell++; // increase cells printed count
if($cCell == $numCells){ // last cell, close tbody
$output .= '</tbody>';
}
$i++;
}
/* FINISH table printing */
$output .= '</table>';
$output .= '</div>';
return $output;
}
I hope that this answer is useful to you someday.
The title states 5 columns, but your example shows 3. I'll assume 3.
After storing your data in an array, and sorting them, do the following:
For 3 columns, you want position 0,3,6 on the same row. The next row will have increments of 1 of each of those values. So, 1,4,7. The next row will be 2,5,8.
Therefore, you can change your for loop to hold 3 values initially. 0,3,6, and then increment each, and create the next row.
Here is what worked for me. Note that the columns are reset based on the rowCount after it is discovered on the line I labeled(// Added line). You can see I am using a screenWidth and itemWidth to compute my number of columns.
A problem occurs when the number of empty items is greater than the number of rows. If I have 8 columns and 17 records I get 3 rows(Ceiling(17 / 8) = 3). This is a problem (3 * 8) - 17 = 7 empty records. And this is what happens:
RECORD RECORD RECORD RECORD RECORD RECORD ------ ------
RECORD RECORD RECORD RECORD RECORD RECORD ------ ------
RECORD RECORD RECORD RECORD RECORD ------ ------ ------
Since rows are 3 then the line of code that I added fixes things:
columnCount = Math.Ceiling(itemCount / rowCount);
columnCount = 17 / 3 Ceiling = 6(columns) so my layout renders as follows (my client works out the widths).
RECORD RECORD RECORD RECORD RECORD RECORD
RECORD RECORD RECORD RECORD RECORD RECORD
RECORD RECORD RECORD RECORD RECORD ------
Hopefully that helps out anyone who was facing my issue.
private List<CompanyCourseViewModel> Reorder(List<CompanyCourseViewModel> courses, Decimal width, Decimal itemWidth)
{
var list = new List<CompanyCourseViewModel>();
var columnCount = Math.Floor(width / itemWidth);
var itemCount = courses.Count();
var rowCount = Math.Ceiling(itemCount / columnCount);
columnCount = Math.Ceiling(itemCount / rowCount); // Added line.
for (var i = 0; i < rowCount * columnCount; i++)
{
var index = (int) ((i%columnCount) * rowCount + Math.Floor(i/columnCount));
if (index < itemCount)
{
courses[index].NumColumns = (int) columnCount;
list.Add(courses[index]);
}
else
{
list.Add(new CompanyCourseViewModel()
{
Id = -Math.Abs(i - courses.Count()),
Title = "----",
NumColumns = (int)columnCount
});
}
}
return list;
}