i need a little help on foreach - php

This is my cats in mysql
cats_id cats_position cats_parentid
1 1> 0
2 1>2> 1
3 3> 0
4 1>2>4> 2
and i am trying to create a navigation like:
index > cars > fiat > punto
from
cat=4&parent=2&position=1>2>4>
I end up getting:
Index carcarcarcar
and my php knowledge is not enough to finish this code. can you help me please.
<?php
$position = trim($_GET['position']);
$pieces = explode(">", $position);
$i=0;
foreach($pieces as $piece){
$result = mysql_query("SELECT * FROM cats
WHERE cats_id='".$pieces[$i]."'");
while($row = mysql_fetch_array($result))
{
$piecesid[$i] = $row['cats_id'];
$piecesname[$i] = $row['cats_name'];
$piecesposition[$i] = $row['cats_position'];
}
$i++;
}
?>
Index
<?php $i=0; foreach($pieces as $piece){
if($i=0)
$parent=0;
else
$parent=$placesid[$i-1];
echo '<a href="cats.php?cat='.$piecesid[$i].'&parent='.$parent.'&position='.$piecesposition[$i].'">'.$piecesname[$i];
}

Your first error is a missing semicolon here:
$i++;
The second bug is a missing dot after $parent in the echo line:
'&parent='.$parent.'&position='
The third (unexpected end) error will become apparent when you started to indent your code correctly. It's also bad style to omit the curly braces, because that makes it more difficult to find precisely such errors.
And lastly: when posting on Stackoverflow, include the full error message (which always mentions the line number!)

I believe this is what he is looking for:
Create a mysql table with id, parent_id, and name fields.
When a category is a "child" of another, that others parent_id field should be set accordingly, I see you already have something to that effect.
Use this code, setting $cat via $_GET['cat'] or something.
<?php
$cat = mysql_real_escape_string($_GET['cat']);
$res = mysql_query("select id,name,parent_id from categories where id = '$cat'");
$breadcrumb = array();
while ($category = mysql_fetch_object($res) {
$breadcrumb[] = "" . $category->name . "";
if ($category->parent_id != 0) {
$res = mysql_query("select id,name,parent_id from categories where id = '{$category->parent_id}'");
}
}
echo join(" > ", array_reverse($breadcrumb));
?>

You have not closed your foreach in the last php section
<?php $i=0; foreach($pieces as $piece){
if($i=0)
$parent=0;
else
$parent=$placesid[$i-1];
echo '<a href="cats.php?cat='.$piecesid[$i].'&parent='.$parent'&position='.$piecesposition[$i].'>'.$piecesname[$i];
//Missing } here
?>

you're missing a } at the end. Just put a } after the last line like this:
echo '<a href="cats.php?cat='.$piecesid[$i].'&parent='.$parent'&position='.$piecesposition[$i].'>'.$piecesname[$i];
}

By the way, you don't need cats_position in your table.
To handle hierarchical data like this you can use a nested set (http://en.wikipedia.org/wiki/Nested_set_model) or just rely on the parent_id.
The advantage of this is, that you for example don't need multiple parameters in your get query. Instead of
cat=4&parent=2&position=1>2>4>
you then archieve the same with:
cat=4

Related

Adding commas to a loop within a loop

I'm trying to create a list using a loop within a loop. I have 3 tables.
T1: faculty
T2: keywords
T3: facID, keywordID
I've created a select statement to cross join the rows and spit out something like this:
Faculty Name A
keyword-a keyword-b keyword-c
Faculty Name B
keyword-a keyword-d keyword-f
Everything works great except I need to add commas to the keyword list and my code isn't doing the trick. My keywords are still looping through without the comma.
<?php while ($row = mysql_fetch_assoc($result)) { ?>
<?php if ($row['facID'] !== $lastID ) { ?>
<?php echo $row['facname']; ?><br />
<?php $lastID = $row['facID']; ?>
<?php } ?>
<?php $kwords = array();
foreach($row as $k => $v) {
if (strpos($k, 'kword') === 0) {
$kwords[] = $v;
}
}
echo implode(', ', $kwords);
} ?>
Any suggestions? I'm a noob and I'm hoping it's something very obvious!
There seem to be a few issues with your code, so I'll try to address them all.
First, you have a lot of opening and closing <?php> tags, and it's really messing with the readability of your code. Consider keeping as much code as possible contained into a single <?php> code block. For example, instead of this:
<?php if ($row['facID'] !== $lastID ) { ?>
<?php echo $row['facname']; ?><br />
<?php $lastID = $row['facID']; ?>
<?php } ?>
...you can consolidate all of that PHP code into this:
<?php
if ($row['facID'] !== $lastID ) {
echo $row['facname'] . "<br />";
$lastID = $row['facID'];
}
?>
Next, you're not outputting any sort of visual break after echoing out your implode()ed array. This would lead to the next heading being output on the same line as the output of your previous heading. For example, your first two headings will end up like this:
Faculty Name A
keyword-a keyword-b keyword-cFaculty Name B
keyword-a keyword-d keyword-f
Notice how Faculty Name B is at the end of the line of keywords?
Finally, I think the problem you're reporting is that you're getting two keywords that are linked together. For example, if you had two rows of data with the same facility id, one with keywords keyword-a and keyword-b and another with keyword-c and keyword-d, you would see that output visually without a comma between keyword-b and keyword-c.
In other words, instead of this:
keyword-a, keyword-b, keyword-c, keyword-d
...you're instead seeing this:
keyword-a, keyword-bkeyword-c, keyword-d
This is also caused by the lack of a visual break between implodeed lines, but I believe the problem is deeper than that. I believe you want all keywords for a given facility to be shown on a single line, not broken across multiple lines. For that, you need to move where you reinitialize your array so that it gets reinitialized at the same time you switch to a new heading. Try something like this:
$kwords = array();
while ($row = mysql_fetch_assoc($result)) {
if ($row['facID'] !== $lastID ) {
if ($kwords) {
echo implode(", ", $kwords) . "<br />";
$kwords = array();
}
echo $row['facname'] . "<br />";
$lastID = $row['facID'];
}
foreach($row as $k => $v) {
if (strpos($k, 'kword') === 0) {
$kwords[] = $v;
}
}
}
if ($kwords) {
echo implode(", ", $kwords);
}
echo "<br />";
This still isn't the best code, but you can refactor it.
The idea here is that the array gets output and reset every time the facility changes, so that the array encompasses all keywords for that facility and they all get output together, rather than being reported only as part of the database row they were returned with. After the loop completes, you have to manually report the last row since the usual reporting is taken care of within the loop.

While loop only retrieving one result

UPDATE: Still can't seem to figure it out. If anyone can lend a hand, it would be appreciated ^^.
I am having a problem and I'm not sure where my code is breaking down. I have a 'follow' function where you can follow different registered users. Their userID's of who you followed are stored in an array (follower_array). It's retrieving each member from the array, but of each member that's followed instead of displaying all the content, it's only displaying the 1 latest one from each member.
$broadcastList= "";
if ( $follower_array != "" ) {
$followArray = explode(",", $follower_array);
$followCount = count($followArray);
$i = 0;
$broadcastList .= "<table>";
foreach( $followArray as $key => $value ) {
$i++;
$sqlName = mysql_query("
SELECT username, fullname
FROM members
WHERE id='$value'
LIMIT 1
") or die ("error!");
while ( $row = mysql_fetch_array($sqlName) ) {
$friendUserName = substr($row["username"],0,12);
}
$sqlBroadcast = mysql_query("
SELECT mem_id, bc, bc_date, device
FROM broadcast
WHERE mem_id='$value'
ORDER BY bc_date ASC
LIMIT 50
") or die ("error!");
while ( $bc_row = mysql_fetch_array($sqlBroadcast) ) {
$mem_id = $bc_row['mem_id'];
$bc = $bc_row['bc'];
$dev = $bc_row['device'];
$bc_date = $bc_row['bc_date'];
$broadcastList .= "<td><a href='member.php?id=' .$value. ''>
$friendUserName</a> • $when_bc • Via: $dev <b>$bc</b></td></tr>";
}
broadcastList .= "</table>";
}
}
So, it's retrieving the members entirely, but not more than their single latest "broadcast." Any insight would be appreciated.. thank you!
Here's what's happening:
while( $row = some_next_result_function() ){
$result = $row["thing"];
}
Is going to overwrite $result every time, so you'll only end up with the last result.
You need to make a list and append to it instead.
I'm gonna take a shot in the dark:
$broadcastList .= "<td><a href='member.php?id=' .$value. ''>
$friendUserName</a> • $when_bc • Via: $dev <b>$bc</b></td></tr>";
That line pretty much misses a starting "tr" element. Are you sure the content isn't shown simply because of the faulty html markup?
Also:
broadcastList .= "</table>";
You're missing the $ there ;).
I don't know if this fixes it or even helps you; but I sure hope so :). Alternatively; you can also check the HTML source to see if the entries really aren't there (see first remark).

PHP while loop to get values from mysql data base if it equals the $i value

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.

How to process HTML form that has dynamic elements?

Apologies if this is somewhat of a duplicate question, I did see others but I didn't quite find what I was looking for.
You can see my code in the following jsfiddle: http://jsfiddle.net/ZnWMq/
As you can see, I have named my drop-downs tags[], values[] and operands[] - i.e. as arrays so that whatever PHP page we set as the action of the form will be able to process the dynamically added drop-downs.
I'm just a bit confused on how to split out the values once they are sent to the page dealing with the form submission so if anyone can shed some light I would be very grateful.
Regards,
Martin
UPDATE
Hi, thanks for your replies.
so far I have changed the action of the form to advancedsearch.php using the POST method and here is the code:
<?php
$tags = $_POST['tags'];
$operands = $_POST['operands'];
$values = $_POST['values'];
foreach ($tags as $t)
{
echo "$t<br />";
}
foreach ($operands as $o)
{
echo "$o<br />";
}
foreach ($values as $v)
{
echo "$v<br />";
}
?>
This gets the values ok but it just needs tweaked so I can get it into a format for querying a MySQL database, so something like SELECT * FROM table_name WHERE tag1 operand1 value1 radio_button_value(AND or OR) tag2 operand2 value2 radio_button_value etc
Hope that makes sense.
So when you click 'Advanced Search'
you want to get the values of the
s ? – Alex Thomas 6 mins ago
If this is the case, then this should help: http://jsfiddle.net/ZnWMq/1/
I've done the code to work on the clicking of a span as i didn't want to disrupt your code. Heres my code:
$('#click').click(function(){
tags = $("select[name='tags[]'] option:selected").val();
operands = $("select[name='operands[]'] option:selected").val();
values = $("select[name='values[]'] option:selected").val();
output = tags+" "+operands+" "+values;
alert(output);
});
If this is not what you're after, i'll try again :)
In this case you will receive 3 post variables as arrays and they should have equal length (in term of count). You will need code like that:
$filterCount = count($_POST['tags']);
$filters = array();
for ($i = 0; $i < $filterCount; $i++) {
$filters[] = array('tag' => $_POST['tags'][$i], 'operand' => $_POST['operands'][$i], 'value' => $_POST['values'][$i]);
}
Also you can try different approach. For example you can use different name for each filter like that:
<select name="filter1[tag]" class="tags">
<option>tags</option>
</select>
<select name="filter1[operand]" class="operands">
<option>operands</option>
</select>
<select name="filter1[value]" class="values">
<option>values</option>
</select>
When you clone the filter you have to change the name to filterN.
managed it by doing the following:
<?php
$tags = $_POST['tags'];
$operands = $_POST['operands'];
$values = $_POST['values'];
$cat = $_POST['cat'];
print "<pre>";
print_r ($_POST);
$query .="WHERE ";
for ($counter=0 ; $counter < count($tags) ; $counter++)
{
if ($counter>0)
{
$query .= "$cat ";
}
$query .= sprintf("%s %s '%s' ", $tags[$counter] , $operands[$counter] ,
$values[$counter]) ;
}
echo "$query";
?>

PHP Order in alphabetical order

I'm trying to make a simple alphabetical list to order items in my database. The thing I can't figure out is how to actually list it.
I would like it to be the same format as you have on miniclip.com
Here's an image
I looked around, but couldnt find an answer really.
(I would like it to finish even at the end of each vertical column, except the last one for sure)
Any help would be welcome!
In MySQL:
SELECT * FROM table ORDER BY name ASC
In PHP:
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
foreach ($fruits as $key => $val) {
echo "fruits[" . $key . "] = " . $val . "\n";
}
fruits[0] = apple
fruits[1] = banana
fruits[2] = lemon
fruits[3] = orange
Assuming that your result set already is sorted by using the ORDER BY clause, to group the results by their first character you just need to remember the first character of the previous entry and print out the first character of the current entry if they are different. So:
$prevLabel = null;
while ($row = mysql_fetch_assoc($result)) {
$currLabel = strtoupper(substr($row['name'], 0, 1));
if ($currLabel !== $prevLabel) {
echo $currLabel;
$prevLabel = $currLabel;
}
echo $row['name'];
}
This will print the first character as a label for each group that’s members have the same first character.
He doesn't seem to have an issue with the storting, but doing the column format and headers for each new letter.
Suppose $arr contains your alphabetically sorted list with numeric keys. each element has indexes 'name' and 'link'. This should be pretty safe assumption for data from a SQL query.
$firstLetter = -1;
$desiredColumns = 4; //you can change this!
$columnCount = (count($arr)+27)/$desiredColumns+1;
echo "<table><tr><td>";
foreach($arr as $key => $cur)
{
if ($key != 0 && $key % desiredColumns == 0) echo "</td><td>";
if ($cur['name'][0] !== $firstLetter)
{
echo "<strong>$firstLetter</strong> <br />"; $firstLetter = $cur['name'][0];
}
echo "".$cur['name']."<br />";
}
echo "</td><tr></table>";
You'll have to treat numbers as a special case, but this is the idea. If you are using a template engine there are obviously better ways of doing this, but I figure you would have mentioned that. This is a rough sketch, making pretty HTML isn't my thing.
--Query-- get table into $arr. I can't see your tables obviously, Im making assumptions if names nad stuff so you'll need to verify or change them
$sql = "SELECT * FROM table T ORDER BY name";
$conn = //you should have this
$res = mysql_query($sql, $conn);
$arr = array();
while($row = mysql_fetch_assc($res)
$arr[] = $row;
// start above code here. This isn't safe for empty query responses or other error but it works
I presume you're using MySQL (or another SQL) database, in which case you should simply retrieve the data in the required order using a SORT BY clause on the lookup SELECT. (Sorting this PHP is trivial via the sort function, but it makes sense to get the database to do this - that's pretty much what it's for.)
In terms of balancing the output of each of the columns, you could get a COUNT of the required rows in your database (or simply use the count of the resulting PHP array of data) and use this to ensure that the output is balanced.
As a final thought, if this is going to be output on a per-page basis, I'd highly recommend generating it into a static file when the structure changes and simply including this static file as a part of the output - generating this on the fly is needlessly resource inefficient.
The mysql option mentioned above is definitely the best bet. If the data comes out of the DM in order, that's the simplest way to go.
Your next option might be to look at the
asort and ksort functions in PHP to find the exact one you're looking for.
http://www.php.net/manual/en/array.sorting.php
How are you pulling the data?
<?php
$result = mysql_query("SELECT titles FROM gamelist ORDER BY title ASC");
while ($row = mysql_fetch_assoc($result)) {
echo "{$result['title']}<br/>";
}
?>
There are two ways to do it.
You could use your database and use the 'order' clause to pull them by a specific field alphabetically.
You could also use either a key sort or value sort on a PHP array.
The PHP functions are sort($array) and ksort($array).
http://php.net/manual/en/function.sort.php
http://php.net/manual/en/function.ksort.php
<?php
$list = $your_list_array_from_database
//if you need info on how to do this, just let me know
sort($list);
foreach($list as $item) {
echo $item;
}
?>
I found this post and had the same problem. I used the code below to output a list by category name with a header equal to the first letter. In my database table (category) I have name and category_letter. So, name = football and category_list = 'F'.
<section>
<?php
try {
$cats_sql = $dbo->prepare("SELECT name, category_list, FROM category WHERE category_list REGEXP '^[A-Z#]' GROUP BY category_list ASC");
$cats_sql->execute();
$results_cats = $cats_sql->fetchAll();
} catch(PDOException $e) {
include('basehttp/error');
}
$array_cats = $results_cats;
if(is_array($array_cats)) {
foreach($array_cats as $row_cats) {
$cat_var = $row_cats[category_list]; // Each Category list title
?>
<aside>
<h1><a name=""><? echo $cat_var ?></a></h1>
<?php
try {
$search_sql = $dbo->prepare("SELECT name, category_list FROM category WHERE category_list=:cat_var ORDER BY name ASC"); // Pulling a list of names for the category list
$search_sql->bindParam(":cat_var",$cat_var,PDO::PARAM_STR);
$search_sql->execute();
$results_search = $search_sql->fetchAll();
} catch(PDOException $e) {
include('basehttp/error');
}
$array_search = $results_search;
if(is_array($array_search)) { // Output list of names which match category
foreach($array_search as $row_search) {
?>
<h2><?php echo $row_search[name]; ?></h2>
<br class="clear">
<?php
}
}
?>
</aside>
<br class="clear">
<?php
}
}
?>
</section>
Its actually Simple....I did similar thing for my project once. I had to pull out all music albums name and categorize them in alphabetical order.
In my table, "album_name" is the column where names are stored.
$sql= "select * from album_table order by album_name ASC";
$temp_char= ""; // temporary variable, initially blank;
using while loop, iterate through records;
while($row= $rs->fetch_assoc())
{
$album_name= $row['album_name'];
$first_char_of_albm= $album_name[0]; // this will store first alphabet;
$first_char_of_albm= strtoupper($first_char_of_albm); // make uppercase or lower as per your needs
if($temp_char!=$first_char_of_albm)
{
echo $first_char_of_albm;
$temp_char= $first_char_of_albm; // update $temp_char variable
}
}
That's it....
I am posting my answer to this old question for 3 reasons:
You don't always get to write your queries to MySQL or another DBMS, as with a web service / API. None of the other answers address PHP sorting without query manipulation, while also addressing the vertical alphabetical sort
Sometimes you have to deal with associative arrays, and only a couple other answers deal with assoc. arrays. BTW, my answer will work for both associative and indexed arrays.
I didn't want an overly complex solution.
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.
Some things to note:
$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 = 4; // 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++;
}
$output .= '</table>';
$output .= '</div>';
return $output;
}
I hope that this code will be useful to you all.

Categories