I want to create a dynamic drop down menu using PHP and MySQL. Menus is OK but not the way I wanted.
I want the menu like this as below (sorted vertically and limiting number of items vertically and horizontally)
I tried achieving this as per below code:
<?php foreach ($result as $riw) { ?>
<div class="four columns">
<li><a href="<?php echo $riw['fmprmlink']; ?>"><?php echo
$riw['remedy_name']; ?></a> </li>
</div>
<?php } ?>
By above approach i am getting this as a result which is not rquired
and without using <div class="four columns"> the result is as below which is again not required
I want items to be arranged and shown alphabetically vertically.
A simple possibility of sorting first, then second, then etc. column.
Can something be improved.
Shows one of many possibilities.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>4 columns</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<?php
function setline($conte,$i,$count,$ILines){
$act1 = $i;
$act2 = 1*$ILines + $i;
$act3 = 2*$ILines + $i;
$act4 = 3*$ILines + $i;
echo "<li>".$conte[$act1]."</li>\n"; // 0
if ($act2 < $count){ echo "<li>".$conte[$act2]."</li>\n";}
if ($act3 < $count){ echo "<li>".$conte[$act3]."</li>\n";}
if ($act4 < $count){ echo "<li>".$conte[$act4]."</li>\n";}
}
//-----------main---------------
echo "<ul id=\"quad\">";
$anArry = array("CSS","XHTML","Semantics","Accessibility","Usability","Web Standards","PHP","Typography","Grids","CSS3","HTML5");
sort($anArry);
$count = count($anArry);
$Idiv = (int)($count/4);
if ($count - ($Idiv * 4)>0) {$ILines = $Idiv+1;} else {$ILines = $Idiv;}
for ($i = 0; $i < $ILines; $i++) {
setline($anArry,$i,$count,$ILines);
}
echo "<ul/>";
?>
</body>
</html>
Next is the normal standard look of a 4 column list.
To get it we changed only the for loop.
Sorted from left to right ( not what OP wants)
for ($i = 0; $i < $count; $i++) {
echo "<li>".$anArry[$i]."</li>\n";
}
Now that we know the matrix ...
1| 0-2 3-5 6-8 9-11
col| 1 2 3 4
---|---------------
r 1| 0 3 6 9
o 2| 1 4 7 10
w 3| 2 5 8 11
... we can write a simpler function.
function sortfor4c($cont,$i,$ILines,&$ICol,&$IRow){
echo "<li>".$cont[$ICol * $ILines - $ILines + $IRow -1]."</li>\n";
$ICol++;
if ($ICol > 4) {
$ICol = 1;
$IRow++;
}
}
....
$ICol = 1;
$IRow = 1;
for ($i = 0; $i < $count; $i++) {
sortfor4c($anArry,$i,$ILines,$ICol,$IRow);
}
style.css
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6{
margin:0;
padding:0;
}
ol,ul{
list-style:none;
}
body{
font-family:Georgia, "Times New Roman", Times, serif;
color:#333;
}
ul{
width:760px;
margin-bottom:20px;
overflow:hidden;
border-top:1px solid #ccc;
}
li{
line-height:1.5em;
border-bottom:1px solid #ccc;
float:left;
display:inline;
}
#quad li { width:25%; }
Presumably, you would want to use some sort of for loop to order the data appropriately. You could do this with PHP or you could do it with JavaScript.
Either way, you will need to process the entries returned by the server so as to limit the number of rows added to each column. The way you'll process the data depends on how it is returned by the server. If the server sends JSON data representing the data cells in question (and you're using AJAX), you'll likely need to take a javascript approach. If you plan to load all menu field data upon the initial page load, you can probably use PHP to create the menu entries.
This is an example of using a for loop to create a table using PHP. You should be able to do the same thing with either list items and/or divs. If this answer is confusing, there are numerous other examples on both SO and the internet at large.
<?php
echo "<table border='1'><br />";
for ($row = 0; $row < 5; $row ++) {
echo "<tr>";
for ($col = 1; $col <= 4; $col ++) {
echo "<td>", [YOUR MENU ENTRY GOES HERE], "</td>";
}
echo "</tr>";
}
echo "</table>";
?>
The following code uses 2 loops to create a 4 column table from an assoc array. $z is calculated to sort rows in each column in ascending order.
$count = count($result);
$rows= floor($count/5);
for ($x = 0; $x <= $rows; $x++) {
for ($y = 0; $y <= 4; $y++) {
$z=($rows*$y)+$x+$y;
if($z<$count){
$html .="<td>".$result[$z]['fmprmlink']."</td>\n";
}else{
$html .="<td></td>\n";
}
}
$html .="</tr>\n";
}
$html .="</table>";
echo $html;
Related
I have a table of category, I want to show category data into 4 equal bootstraps 4 rows dynamically, and data must be shown in alphabetically order.
First I am counting the number of data and dividing by 4 then run 4 queries to find the first 25 data and in the second query next 25 data and so on, but looking for a better solution.
$catCount = Category::all()->count();
$inOneRow = intval( $catCount / 4);
What I want
Assuming Category is a table of category names - you can select ALL categories at once and use the ORDER BY clause on the query:
$query = 'SELECT name FROM db.categories ORDER BY name ASC;';
You can alternatively use sort on the result-set:
$query = 'SELECT name FROM db.categories;';
/* execute query here... */
sort($resultSet);
Let's assume you did this, the styling would be easy using bootstrap grid (notice mock result-set in fiddles):
<?php
const NUM_COLS = 4;
$numResults = count($dummyResult);
$numPerCol = round($numResults / NUM_COLS);
?>
<div class="container">
<div class="row">
<?php
for($i = 0, $col = 0; $col < NUM_COLS; $col++){
echo '<div class="col">';
for($colLimit = min($numResults, $i + $numPerCol); $i < $colLimit; $i++){
echo '<div class="row">'.$dummyResult[$i]['category'].'</div>';
}
echo '</div>';
}
?>
</div>
</div>
Here is a fiddle
Easier to understand, albeit probably slower example:
<?php
const NUM_COLS = 4;
$numResults = count($dummyResult);
$numPerCol = round($numResults / NUM_COLS);
?>
<div class="container">
<div class="row">
<?php
for($i = 0; $i < NUM_COLS; $i++){
echo '<div class="col">';
foreach( array_splice($dummyResult, 0, $numPerCol) as $row ){
echo '<div class="col">'.$row['category'].'</div>';
}
echo '</div>';
}
?>
</div>
</div>
Here is a fiddle
Note: Container will be 100% width of it's parent, unless styled otherwise.
Column widths will be equal by default. See Bootstrap Grid.
I have some HTML in a variable that I'd like to loop 4 time per row. I am making a couple of queries first. In one I get the number of rows and store it in a variable. The second, I am looking to fetch the associated data that I will need to display.
$results = $dbCon->query("SELECT * FROM table WHERE status = '1' ORDER BY id DESC LIMIT $start, $limit");
$total = mysqli_num_rows($results);
$res = $dbCon->query($results);
$data = $res->fetch_assoc();
$link = $data['link'];
$title = $data['title'];
$image = $data['image'];
$imgAlt = $data['imgAlt'];
Third, I store what I want to display in a variable. The HTML I plan on displaying looks something like this
$html = printf("<div style=\"text-align:center; max-width:270px; white-space:normal; word-wrap:break-word; border-left:1em solid transparent; border-right:1em solid transparent; text-overflow: ellipsis; float:left;\">
<a href=\"%s\">
<img style=\"width:270px; height:232px; margin-bottom:40px; border-radius:45px; -moz-border-radius:45px; -webkit-border-radius:45px; box-shadow:0px 0px 3px #fff; -moz-box-shadow:0px 0px 3px #fff; -webkit-box-shadow:0px 0px 3px #fff;\" src=\"images/recentshoots/%s\" alt=\"%s\" />
<p>%s</p> <br /></a>
</div>", $link, $image, $imgAlt, $title);
Next, I would like to loop the 20 items per page in 4 items per row. This is where I am having some trouble. My issue is that the number of characters in the $title are always different so the layout breaks apart. At first a tried a simple way using css and php to do a str_pad() but it doesn't seem to work right with empty spaces. I always get some containers that are taller than others which distorts my row. So I did some research in this platform to model after someone else example.
I m having some trouble with what I found because the examples I've seen have information missing that I need to understand how to modify my own. I have seen it done with foreach and while loops. Can someone help me find a way to understand this better?
How can I loop the data retrieved and make sure that only 4 per row exist in a page of 20 items? Thank you so much for your help. I started with something like this
$startingPoint = 1;
echo "<div class=\"row\">";
foreach($startingPoint < 4){ //this foreach is not even starting the right way, how can I fix this?
echo $html;
}
Can I use a foreach? or a while loop? or do-while?
which one is the best solution and the fastest or most efficient way to go? The shorter the code the better.
Foreach loops are used for array datatypes whilst a while loop can be used for booleans and more.
What you're looking for is a for loop, this allows your to set a counter and each time the loop is ran it adds to a counter. Once the expression is met, it ends the loop.
for($i = 1; $i == 4; $i++)
{
echo 'Loop ' . $i . ': This will loop 4 times';
}
However, you could fix your foreach by using this snippet:
$startingPoint = [1,2,3,4];
foreach($startingPoint as $start)
{
echo $html;
}
Since there are 4 items inside the array, the loop will continue 4 times.
Your SQL is returning more than one row of data thus creating $data to become multidimensional, your loop therefore may not work how its written, you could try this:
for($i = 1; $i >= $limit; $i++)
{
print_f(<!-- html here -->, $data[$i]['column']);
}
You can try this code. Full pagination and view:
Example: index.php
<?php
//get page id for pagination and limit query
$limit = 4;
if(isset($_GET["page"]))
$page = intval($_GET["page"]);
else
$page = 1;
$total = $limit * $page;
$start = $total - $limit;
//GEt data from database. I have used mysqli for testing purpose.
$conn=mysqli_connect("localhost","root","","dbname");
$result = mysqli_query($conn, "SELECT * FROM table WHERE status = '1' ORDER BY id DESC LIMIT $start, $limit");
$total = mysqli_num_rows($result);
?>
<!--Your html code what you want-->
<table>
<tr>
<th>Title</th>
<th>Image</th>
<th>Link</th>
</tr>
<!--loop inside html-->
<?php while($data = mysqli_fetch_assoc($result)) { ?>
<tr>
<td><?php echo $data['title']; ?></td>
<td><img src="<?php echo $data['image']; ?>" alt="<?php echo $data['imgAlt']; ?>"> </td>
<td>Link</td>
</tr>
<?php } ?>
</table>
<?php
/**======== Pagination Url generate=============*/
$totalPages = ceil($total/$limit);
if($page <=1 ){
" <span style='font-weight: bold;'> < Prev </span> ";
}else{
$j = $page - 1;
echo " <a href='index.php?page=$j'>Prev</a> ";
}
for($i=1; $i <= $totalPages; $i++){
if($i<>$page){
echo " <a href='index.php?page=$i'>$i</a> ";
}else{
echo " <span style='font-weight: bold;'>$i</span> ";
}
}
if($page == $totalPages ){
echo " <span style='font-weight: bold;'>Next ></span> ";
}else{
$j = $page + 1;
echo " <a href='index.php?page=$j'>Next</a></span> ";
}
?>
I have a database that contains donor information and then have PHP pages that pull that data and display it under the donor's specific category.
The code I am using is as follows:
// 10,000 DONORS
echo "<p><b>$10,000 cont.</b></p>";
$sql = "SELECT * FROM donor WHERE DonationAmount = 10000 AND Category = '1' or DonationAmount = 10000 AND Category IS NULL ORDER BY LastName ASC LIMIT 10000 OFFSET 6";
$result = mysqli_query($conn, $sql);
$i = 0;
$total_rows = $result->num_rows;
echo "<table><tr>";
if (mysqli_num_rows($result) > 0) {
// output data of each row
while ($row = mysqli_fetch_assoc($result)) {
// test if the DisplayName field is empty or not
echo "<td>";
if (empty($row['DisplayName'])) {
// it's empty!
if (empty($row['FirstName'])) {
echo $row['LastName'];
}
else {
echo $row["LastName"] . ", " . $row["FirstName"];
}
} else {
// Do stuff with the field
echo $row["DisplayName"] . "";
}
echo "</td>";
$i++;
if ($i % 2 == 0 && $i != $total_rows) {
echo "</tr><tr>";
}
}
} else {
} echo "</tr></table>";
My question is as follows: right now the names are inserted into the table in a manner that makes the read left->right->left->right etc. I need them to show up like a normal list works and reads top to bottom, and rolls to the next column when it is told to (counter?). How can I do this?
Here is a preview off the page
EDIT: tried this code:
$sql = "SELECT * FROM donor WHERE DonationAmount = 1000 AND Category = '1' or DonationAmount = 1000 AND Category IS NULL ORDER BY LastName ASC";
$result = mysqli_query($conn, $sql);
$i = 0;
$count = 0;
$total_rows = $result->num_rows;
$halfsize = $total_rows / 2;
$FirstArray = array();
$SecondArray = array();
while ($row = mysqli_fetch_assoc($result)){
while ($count <= $halfsize){
$FirstArray[] = $row['DisplayName'];
//echo "$FirstArray[$count]";
$count++;
}
$SecondArray[] = $row['DisplayName'];
//echo "$SecondArray[$count]";
}
echo "<table>";
for($j=0; $j<count($FirstArray); $j++){
echo "<tr><td>". $FirstArray[$j] . "</td><td>" . $SecondArray[$j] . "</td> </tr>";
}
echo "</table>";
And I just get the same field (the first result) for all of the first column (The First Array?) and then the second column (SecondArray) contains all of the results.
Your issue is not your PHP or your MySQL but your output handling.
So there's an array of data that's being dumped on your HTML and you need to order it to look nice . Two columns reading left to right in a table format.
The <table> tag is perfect for this, and while most people hate the table tag, it is useful for tabled data.
It's worth noting that due to the flexibility and accommodating nature of CSS/HTML that this is not the only correct way but one of many ways this issue can be addressed
Method:
You have a while loop outputting one unit at a time, a unit in this case being a name in a <td></td> block. So that's your unit:
while {
print "unit";
}
So if you have two columns you want to arrange then you need to tell the while loop to distinguish between the first and the second column, this can be done with detecting if the counter (+1 for each itteration) is odd or even.
You can do this with the modulus divisor in PHP:
while {
counter++
if (counter%2) == 1 ){
//odd number.
}
}
So to sum it all up and give you a basic example:
$output = "";
$rowsTotal = mysqli_num_rows($result); //from your original code.
$counter = 0;
while ($row = mysqli_fetch_assoc($result)) {
$counter++; //plus 1 each itteration
if (($counter%2) == 1){
/// is odd so open the row of the table.
$output .= "<tr>";
}
$output .= "<td>";
if (empty($row['DisplayName'])) {
// it's empty!
if (empty($row['FirstName'])) {
$output .= $row['LastName'];
}
else {
$output .= $row["LastName"] . ", " . $row["FirstName"];
}
}
else {
// Do stuff with the field
$output .= $row["DisplayName"] . "";
}
$output .= "</td>";
if (($counter%2) == 0){
// if even so close the row of the table.
$output .= "</tr>";
}
// special case: If there area total of odd number of outputs
if($counter == $rowsTotal && $counter%2 == 1){
// so the last counter value is an odd number so force closure
// of </tr> (or add a blank space)
$output .= "<td> </td></tr>
}
} //end while.
...
print "<table>";
print $output;
print "</table>";
I don't want to dive deep into getting really creative with CSS but you can use CSS to finesse and improve the core HTML output setout above with some wonderful Cascading Style sheets, but above is a very rough outline of the sortof approach you could use to simulate a base level intelligence for the script to output names in the layout you are looking for.
Good luck.
CSS example:
table td {
background-color:#000;
color: #fff;
font-size:1.5rem;
text-align:left;
width:49%; /* 50% sometimes causes overflow, so set a tiny bit smaller */
padding:0.25rem;
margin:0;
box-sizing: border-box;
}
VERSION 2
From comments, OP Needs the results from the SQL query to be two columns, rather than two rows. This means that table (a row structure) is inappropriate for this output and so instead we should use a more customised CSS / div tag set:
The layout would be two columns of approximatly 49% width each, and then each column contains block elements, This blob of blocks will then need to be split in half and a divider added to generate two shorter columns from one long one.
The block elements are output in a foreach loop and once the halfway point is met then an extra HTML code is inserted to break the elements up into a second <div> . this is a little bit hacky it feel to me, but, does the job.
requirements:
A predefined counter of result rows. One can easily be generated. And that the SQL query is already ordered in the intended way, using MySQL ORDER BY.
Semi-Pseudo code:
$array = SQL data result.
$counter = counter of how many array rows are returned.
$divisorCount = ceil($counter /2);
$foreachCount = 1
foreach ($array as $row){
$foreachCount++;
$block[] = "<div class='block'>".$row['data']."</div>\n";
if($foreachCount > $divisorCount){
$foreachCount = 0; //reset, as this will not be true again.
end($block);
$key = key($block); //most recent block array reference.
$block[$key] .= "</div><div class='column'>"; //the insert.
}
}
unset($row,$key,$foreachCount,$divisorCount); //tidyup.
The above generates a bunch of array elements, one for each name. There is an inserted splitter that ends the initial column and starts a second column, finally we wrap the whole block array into a final <div> wrapper.
$output = "<div class='tableContainer'>
<div class='column'>".implode($block)."</div>
</div>";
The above output will be the opener for the first column but the closer for the second column. Within output we now have the complete columns for two columns of all results contained in a Div Container element.
The following CSS classes would need some tweaking to get right but should be a start:
CSS
.block{
line-height: 2rem;
display:block;
padding:0.25rem;
box-sizing:border-box;
}
.column{
width: 49%;
min-width:150px; /* or whatever. */
display:inline-block;
}
.tableContainer{
max-width: 800px; /* or whatever. */
min-width: 300px; /* or whatever. */
width:100%;
margin:auto; //centres it.
}
The CSS would be 49% rather than 50% because box sizes can have a tendancy to overflow on different browsers (Firefox especially), but the $output would finally be:
HTML
<div class='tableContainer'>
<div class='column'><div class='block'>My Name</div>
<div class='block'>Your Name</div>
<div class='block'>His Name</div></div>
<div class='column'><div class='block'>Their Name</div>
<div class='block'>Her Name</div>
<div class='block'>Smacked HorseBombs</div>
</div>
</div>
You could also possibly substitute display:inline-block for float:left, but thats the basics, have a play on jsfiddle to tweak as you need.
I won't use tables for this. There may be some other css tricks. But for the sake of question, I'm answering.
Create two arrays.
Get the size of resultset with mysqli_num_rows, and divide it by two, then walk through this first array and move them until halfsize into array1. And then remainig into array2.
At the end you'll have something like this
Array 1 Array 2
------- -------
[0] Row 1 [0] Row 4
[1] Row 2 [1] Row 5
[2] Row 3
Then walk through it and fill your html table. (with controlling them against being empty)
for($i=0; $i<count($array1); $i++){
echo '<tr><td>'.$array1[$i].'</td><td>'.$array2[$i].'</td></tr>';
}
I am trying to create a page of results from a mysql database using php, encasing each line of results (which contains an image and some other lines of detail) in a box.
Currently, page.php gets the data from the db, and uses result.inc to format the data into rows of information three cells per row.
Address1 Picture Comment
Address2 Picture2 Comment2
etc.
I would like to encase each row in pretty box (or even just a box). This produces one empty (but bordered) box before the table, then the table as normal.
How to close off the box with the results inside?
<style>
p {
outline-style: solid;
outline-width: 5px;
}
</style>
for($i=1; $i <= $num_rows; $i++) {
$row = mysql_fetch_array($result);
print("<p>");
print("<TR>");
include("includes/result.inc");
print("</TR>");
print("</p>");
}
You can't just put p-tags between table rows. Instead, style the table rows themselves:
<style>
tr {
outline-style: solid;
outline-width: 5px;
}
</style>
And the php:
for($i=1; $i <= $num_rows; $i++) {
$row = mysql_fetch_array($result);
print("<TR>");
include("includes/result.inc");
print("</TR>");
}
I'm trying to make a table of iframes (2 per row) and I query everything, but whenever it prints, everything is on a row of it's own even though I only tell every second one to. I can't figure out why this is happening:
<div id="main" style="width:1000px;">
<?php
$query = "SELECT * FROM scripts";
mysql_connect("localhost", "root", "");
mysql_select_db("scriptsearch");
$results = mysql_query($query);
$num = mysql_num_rows($results);
mysql_close();
?>
<table border="0">
<?php
for($i = 0; $i <= $num; $i++){
if($i % 2 == 0) //is this the second one? if so, make a new row
echo '<tr>';
else{
?>
<td><iframe src="scriptpreview.php?id=<?php echo $i;?>" style="width: 350px; height: 230px;" frameBorder="0" scrolling="no">Your browser needs to support iFrames for this website.</iframe></td>
<?php }if($i % 2 == 0) echo '</tr>';/*end the row*/ } ?>
</table>
</div>`
Edit: I've tried Krynble's solution, but no matter how I modify it, it still doesn't show up how I expect.
There's an error in your loop.
Try this:
<?php
for($i = 0; $i <= $num; $i++){
if($i % 2 == 0) //is this the second one? if so, make a new row
echo '<tr>';
?>
<td><iframe src="scriptpreview.php?id=<?php echo $i;?>" style="width: 350px; height: 230px;" frameBorder="0" scrolling="no">Your browser needs to support iFrames for this website.</iframe></td>
<?php if($i % 2 == 1) echo '</tr>';/*end the row*/ } ?>
<?php if($i % 2 == 1) //close last row in case we haven't done it yet.
echo '</tr>';?>
You should print the iframe unconditionally, not inside an else. Besides, the closing </tr> should be printed when $i is odd.
Other people have commented on the php/html part, let me focus on the query part:
Don't do this:
$query = "SELECT * FROM scripts"; (1) select all ?
mysql_connect("localhost", "root", ""); (3) don't connect as root!
mysql_select_db("scriptsearch");
$results = mysql_query($query); (4) no check for errors?
$num = mysql_num_rows($results); (2) when you only want 1 count?
Do this instead:
$query = "SELECT count(*) as rowcount FROM scripts";
mysql_connect("localhost", "user1", "password");
mysql_select_db("scriptsearch");
if ($results = mysql_query($query)) {
$row = mysql_fetch_row($results);
$num = $row['rowcount'];
} else { echo "error....." }
You don't have an opening <tr> tag in your table. You need to have a table row before you can put data in it.