I have a MySQL database with a table called product. Columns are id, product_name, price, category. I use PDO with fetchAll and sort by category. I would like to create HTML tables for each category grouping. In the past I've always done something like this:
$category = "";
$html = "";
foreach($results as $row){
if ($row['category'] != $category){
if ($category != "")
$html .= "</table>";
$category = $row['category'];
$html .= "<table>";
}
//code for table row here
}
$html .= "</table>";
However, I am wondering if there is a different way to do this such as splitting an array by categories and running a foreach on each sub-array. Is this possible?
Edit:
To explain further, I am looking for something that is not as cumbersome. I prefer not having to check what the previous category was (or if it was empty). I prefer not having to specify a closing </table> tag twice. If an array can be split by category then this would get around these issues by just running a nested loop on each of the categories.
Edit 2:
For some reason this question was listed as opinion based. Can someone inform me as to what is opinion based about my question? I will then try to improve it.
If you wanted to skip the whole category check then yes, you could create a new array.
$productCategories = array();
foreach ($results as $result) {
$productCategories[$result['cat']][] = $result;
}
foreach ($productCategories as $productCategory) {
// Start table
foreach ($productCategory as $product) {
// Render product
}
// End table
}
Related
I have 2 tables. First one is categories and the second is items.
I need my script to print to .txt file the name of the category and underneath it category items with matching 'category_id'. My code uses first while loop to iterate through the categories and second to iterate through items. Everything works fine until we get to second while loop, because then values become empty.
while ($row2 = mysqli_fetch_array($query_for_categories)) {
fwrite($fp, $row2["category_name"].PHP_EOL);
while ($row = mysqli_fetch_array($query_for_items)) {
if ($row2['id_category_from_category'] == $row['id_category_from_items']) {
fwrite($fp, $row["item_name"].PHP_EOL);
}
}
}
After the first iteration of the outer while loop, you will have fetched all the rows from $query_for_categories. There will be no more rows to fetch from that query on subsequent iterations of the outer while loop.
You can fetch them all into an array first
while ($row = mysqli_fetch_array($query_for_items)) {
$items[] = $row;
}
Then use the rows from that array instead of a while ... fetch loop.
while ($category = mysqli_fetch_array($query_for_categories)) {
fwrite($fp, $category["category_name"].PHP_EOL);
foreach($items as $item) {
if ($category['id_category_from_category'] == $item['id_category_from_items']) {
fwrite($fp, $item["item_name"].PHP_EOL);
}
}
}
It does seem like you could probably do this with one query using a join, though. I'd recommend checking into that instead of doing it this way. Based on the column names in your code, the query would be something like this:
SELECT c.category_name, i.item_name
FROM categories c
LEFT JOIN items i on c.id_category_from_category = i.id_category_from_items
ORDER BY c.category_name, i.item_name
Then you could print the items with categories in one loop like this:
$previous_category = null;
while ($item = mysqli_fetch_array($query)) {
// each time category changes, output the new category name
if ($item['category_name'] != $previous_category) {
fwrite($fp, $item["category_name"].PHP_EOL);
// then current category becomes previous category
$previous_category = $item['category_name'];
}
fwrite($fp, $item["item_name"].PHP_EOL);
}
I do wonder how you can tell which of the lines in the file are items and which are categories, though. Maybe you should output some kind of indicator for that?
I need to print a wine list from a database.
I need to print at first a categorie and after all the items that are inside. Thats the order. And i have multiple categorie. So at the end the result will be categorie1, many items, categorie2 many items...
This is the code that i write from now: I think that my problem is to print items according to the id of the alcool_categorie !!
$q_vine = "SELECT * FROM alcool_categorie ";
$r_vine = mysql_query($q_vine,$connection);
$n_vine = mysql_num_rows($r_vine);
$q_bouteille = "SELECT * FROM alcool_item where ALCNID = '$alid'";
$r_bouteille = mysql_query($q_bouteille,$connection);
$n_bouteille = mysql_num_rows($r_bouteille);
for($i = 0; $i < $n_vine; $i++){
echo mysql_result($r_vine,$i,'named').'<br/><br/>';
for($z = 0; $k < $n_bouteille; $k++){
echo mysql_result($r_bouteille,$k,'name').'<br/>';
}
}
I think it's best to use a "JOIN" in your query and then order the rows in the way you want them to be ordered, then you'll only need one loop. While running the loop you compare the category name with the previous category name and if it changes display the category name.
Example
$sql = "SELECT categoryName, bottleName FROM category INNER JOIN bottle ON category.categoryId = bottle.categoryId ORDER BY category.categoryId";
$result = mysql_query($sql,$connection);
$categoryName = ''; //just to make sure the first time the Category is named
while ($row = mysql_fetch_assoc($result)) {
if($categoryName != row['categoryName']){
$categoryName = row['categoryName'];
echo '<h1>'.$categoryName.'</h1>';
}
echo row['bottleName'].'<br/>';
}
Try this after correctly giving the category id field name in the query and inside the first while loop.
$q_vine = "SELECT id, named FROM alcool_categorie ";
$r_vine = mysql_query($q_vine,$connection);
$n_vine = mysql_num_rows($r_vine);
while ($row = mysql_fetch_assoc($r_vine)) {
$categories[$row['id']] = $row;
}
$q_bouteille = "SELECT name, ALCNID FROM alcool_item ";
$r_bouteille = mysql_query($q_bouteille,$connection);
$n_bouteille = mysql_num_rows($r_bouteille);
while ($row = mysql_fetch_assoc($r_bouteille)) {
$items[$row['ALCNID']] = $row;
}
foreach ($categories as $category_id=>$category) {
echo "<ul><li>{$category['named']}<ul>";
foreach ($items[$category_id] as $item) {
echo "<li>{$item['name']}</li>";
}
echo "</ul></li></ul>";
}
You will want to look into PHP's foreach construct. Foreach loops through an entire array of results, for each element inside the array, it extracts its value and optionally also its key. This will not require the use of mysql_num_rows.
Instead of calling mysql_result, you could use mysql_fetch_assoc to get a row's value from your mysql_query. The row's To get all values, you can incorporate this into a loop even. If you do the latter, you can create your own array of key/value pairs and use this inside a foreach construct.
Also note that the use of mysql is outdated, you will want to use mysqli now, which is very similar to mysql.
I have this code here:
<?php foreach($blog_posts['post_category'] as $category) { ?>
How can I get this to work?
Basically I have a database with all my blog posts within them, one of the columns is post_category I'm trying to make a list out of all these by a foreach statement that gets the results like so:
$data['blog_categories'] = $this->db->query("SELECT `post_category` FROM `blog_posts`");
This is codeigniter by the way... Then in my view I have the code:
<?php foreach($blog_posts['post_category'] as $category) { ?>
I need to display each category in an li...
You wanna use implode I think
$output = array();
forreach($blog_posts['post_category'] as $item){
$output[] = "<li>$item</li>";
}
echo "<ul>".implode('',$output)."</ul>";
Or if you were just after the list items and not list just replace the last line with
echo implode('',$output);
Pretty sure what you're looking for is
$data['blog_categories'] = $this->db->query("SELECT DISTINCT `post_category` FROM `blog_posts`");
foreach ($data['blog_categories'] as $category) {
echo "<li>$category</li>";
}
Me, I'd change $data['blog_categories'] to just $blog_categories or something, but I kept it as you had it so as not to confuse the issue.
i want to make a website something like popurls.com, but I will use static data stored in MySQL database. Btw I use php/mysql.
In each list i want to show around 10 links (just like on popurls). In that case, if I would have 20 lists, i would need to make 20 'for' loops (for each particular list).
My question is; is there some better way to print that 20 lists instead of using 20 'for' loops in php.
a for loop or a foreach loop will work fine, but it will be a lot less coding if you just create a single for loop and push content into an array of arrays or an array of strings... you can then do whatever you'd like with the actual content (assuming we're grouping by a column category. I'll use an example that uses an array of strings (and the query that I reference is explained here: http://explainextended.com/2009/03/06/advanced-row-sampling/)
$query = mysql_query([QUERY THAT GETS ALL ITEMS, BUT LIMITS BY EACH CATEGORY]) or die(mysql_error());
$all_items = array();
while($row=mysql_fetch_array($query)){
if (!isset($all_items[$row['category']])){ //if it isn't created yet, make it an empty string
$all_items[$row['category']] = "";
}
$all_items[$row['category']] .= "<li><a href='".$row['url']."'>".$row['title]."</a></li>"; //concatinate the new item to this list
}
Now we have an array where the block of HTML for each section is stored in an array keyed by the name of the category. To output each block, just:
echo $all_items['category name'];
PHP's foreach http://php.net/manual/en/control-structures.foreach.php
Depends a lot on your data input but I could imagine something like this:
<?php
$lists = arrray('list1', 'list2', 'list3');
foreach ($lists as $current) {
$data = fetch_data_from_mysql($current);
foreach ($data as $link) {
echo "Link";
}
}
function fetch_data_from_mysql($current)
{
$list_data = array();
// do whatever is required to fetch the list data for item $current from MySQL
// and store the data in $list_data
return $list_data;
}
You just need two foreach loops. Assuming that you take the data from a mysql table (like you wrote), this could be like this:
$list_query = mysql_query("SELECT * FROM lists";)
while( $list = mysql_fetch_array($list_query) )
{
echo "<h1>{$list['title']}</h1>";
$query = mysql_query("SELECT * FROM entries WHERE list_id = {$list['id']}");
while( $entry = mysql_fetch_array($query) )
{
echo "- {$entry['name']}<br />";
}
}
You can get all the information from the database and parse it into an array, something like
array[<news type1>] = array( link1, link2, link3, etc);
array[<news type2>] = array( link1, link2, link3, etc);
and so on
and on the layout you can use
foreach ($newsCategory AS $categoryLinks) {
foreach ($categoryLinks AS $newsLink) {
<show the link and / or extra data>
}
}
Just store your links in two-dimensional array. That way you'll have to make 1 outer loop (iterating over lists) and 1 inner loop iterating over links in a particular list.
$links = array(
'science' => array('link1', 'link2', ...),
'sports' => array('link1', 'link2'),
// ... and so on
);
foreach ($links as $category => $urls) {
echo "Links in category: $category\n";
foreach ($urls as $url) {
echo $url . "\n";
}
}
Im creating a website, where I make a foreach, that echos out some groups, containing checkboxes, with values and names. At the moment that data comes from a multidimensional array, but writing that array when adding new items, is slow, and not very user-friendly.
At the moment, my foreach looks like this:
echo '<form method="post" action="'.$_SERVER['PHP_SELF'].'">';
/* NEXT WE CREATE OUR FOREACH LOOPS TO ECHO THE HTML FOR LOOKS AND CHECKBOXES */
$totalID=0; // this is a counter we use to build our check box names
foreach ($items as $list){
$totalID++; // add one to the checkbox name counter
echo "<h2>{$list['title']}</h2>\n"; // and echo out our section header
foreach ($list['items'] as $cbox){ // now for each item in the list, call it $cbox
// $cbox now holds the item name, and point value
echo "<label class='checkbox'><input type='checkbox' name='totals[$totalID][]' value='{$cbox[1]}'> {$cbox[0]}</label>\n";
}
}
echo "</form>";
And my array I write is something like this:
$items['computers']['title']='Computer Brand';
$items['computers']['items'][]=array('Apple iMac',1);
$items['computers']['items'][]=array('Apple Macbook',.5);
$items['phones']['title']='Phone Brand';
$items['phones']['items'][]=array('iPhone',1);
$items['phones']['items'][]=array('HTC',1);
As said, I can write this, but takes time.
I want to get it into a database, that data above, but I'm having problems about echo'ing it out, I really can't see how I should do.
My current database looks like this:
http://i.stack.imgur.com/Rj0wQ.png
Anyone that have some tips how to do this easy, and also do it user friendly?
Thank you!
$sql = "SELECT category, title, brand, point FROM yourtable ORDER BY category, title";
$result = mysql_query($sql);
$data = array();
while(list($category, $title, $brand, $point) = mysql_fetch_array($result)) {
if (!isset($data[$category])) {
$data[$category] = array();
}
if (!isset($data[$category]['title'] && (!empty($title)) {
$data[$category]['title'] = $title;
}
if (!isset($data[$category]['items'])) {
$data[$category]['items'] = array();
}
$data[$category]['itemps'][] = array($brand, $point);
}
Your table is just screaming for some normalization, however. It's a horrendous construct.
Well if you dont' want to parse your result into a multi-dimensionnal array like you did before which would be the easiest task but you have to double de CPU work, there is one way i use often in this case:
No1: Make sure your result is sorted by "Category" and then sorted by whatever criteria you want to order your answers as.
No2: Initialize the "$current_category" to NULL
No3: Loop and detect new $categories and output the header as you go. Your script will look like this:
$currentcategory = NULL;
$result = mysql_query($query);
while($row = mysql_fetch_assoc($result)){
//Check for a category change
if($currentcategory != $row['category']){
echo '<h2>'.$row['title'].'</h2>'.PHP_EOL;
$currentcategory = $row['category'];
}
//Output the label
echo '<label class="checkbox"><input type="checkbox" name="totals'.$row['id'].' value="'.$row['point']'."> '.$row['brand'].'</label>'.PHP_EOL;
}