PHP - Query and function and while clause? - php

Question: How can I tie together my query with my function? I would like to print my list, but I am not sure how to connect the two. Also, am I using "entries" correctly below?
/* data handling */
$result = mysql_query("SELECT * FROM Items LEFT JOIN Categories on Categories.CategoryID = Items.FK_CategoryID WHERE Items.FK_UserID = $_SESSION[user_id] ORDER BY CategorySort, CategoryName ASC, ItemSort, ItemTitle");
/* output logic */
function render_list($ItemTitle, array $entries)
{
echo '<ul><li>' . $ItemTitle . '<ul>';
foreach($entries as $entry)
{
echo '<li>' . $entry['ItemID'] . '</li>';
}
echo '</ul></li></ul>';
}
render_list();
Do I need to use a while clause?
// loop through topics
while($row = mysql_fetch_array($result)) {
render_list;
}

Yeah, replace your foreach loop with that while loop. Take that "type" (array) out of the function definition though, you don't need to do that in loosely typed php language. Here's a rework of the code you have:
/* output logic */
function render_list($ItemTitle, $entries)
{
echo '<ul><li>' . $ItemTitle . '<ul>';
while($entry = mysql_fetch_array($entries))
{
echo '<li>' . $entry['ItemID'] . '</li>';
}
echo '</ul></li></ul>';
}
$result = mysql_query("SELECT * FROM Items LEFT JOIN Categories on Categories.CategoryID = Items.FK_CategoryID WHERE Items.FK_UserID = $_SESSION[user_id] ORDER BY CategorySort, CategoryName ASC, ItemSort, ItemTitle");
render_list('My Title', $result);

Related

Menu from database with unlimited sub-menus/items?

I'm trying to build this function that display a menu with sub menus from a database. Something that can show like sub-sub-sub-menus and so on... If that's ever something I need.
In the database i have 2 tables, menu and menuItem.
menu
menuItem
php file
function get_menu($id) {
require(dirname(__FILE__) . '/config.php');
// main base
$menu = " SELECT id, menu_name, menu_data, menu_order
FROM mos_menuItem
WHERE menu_parent_id='$id'
AND menu_sub='0'
ORDER BY menu_order";
$menuResult = mysqli_query($conn, $menu);
echo '<ul>';
while ($menuRow = mysqli_fetch_row($menuResult)) {
// main menu
echo '<li>'. $menuRow[1] .'</li>';
// sub base
$sub = "SELECT id, menu_name, menu_data, menu_order, menu_sub
FROM mos_menuItem
WHERE menu_parent_id='$menuRow[0]'
AND menu_sub>='1'
ORDER BY menu_order";
$subResult = mysqli_query($conn, $sub);
echo '<ul>';
while ($subRow = mysqli_fetch_row($subResult)) {
echo '<li>'. $subRow[1] .'</li>';
}
echo '</ul>';
}
echo '</ul>';
mysqli_close($conn);
}
so I need to loop something inside itself? I'm not sure where to go from here.
Recursion is your best friend here.
I am not sure what purpose is served by the menu_sub field. I assume it tells you at what level it is in the menu hierarchy. If that is the case, then you can safely ignore it (menu_parent_id would suffice) to create this multi-level menu hierarchy.
function getMenus($menu_id, $is_sub=false){
$sql = "SELECT id, menu_name, menu_data, menu_order
FROM mos_menuItem
WHERE menu_parent_id='$menu_id'
ORDER BY menu_order";
$mResult = mysqli_query($conn, $sub);
echo '<ul>';
while ($mRow = mysqli_fetch_row($mResult)) {
echo '<li>'. $mRow[1] .'';
getMenus($mRow[0], true);
echo '</li>';
}
echo '</ul>';
}
This does have one drawback where if you want the hierarchy to start from a parent other than 0 (I assume your root menu_id is 0), that particular menu would not show up in the hierarchy.
So after some trial and error i figure it out. It really helped to look at Sheikh Azad code.
The only difference is in my function i have AND menu_sub='$sub' to make it not going loop the main menu item if the id is the same.. If that make sense.
The function
function mos_get_menu_editor($menuId, $sub) {
require(dirname(__FILE__) . '/config.php');
$item = " SELECT id, menu_name, menu_data, menu_order, menu_sub
FROM mos_menuItem
WHERE menu_parent_id='$menuId'
AND menu_sub='$sub'
ORDER BY menu_order";
$itemResult = mysqli_query($conn, $item);
echo '<ul>';
while ($itemRow = mysqli_fetch_row($itemResult)) {
echo '<li>'. $itemRow[1] .'</li>';
mos_get_menu_editor($itemRow[0], 1);
}
echo '</ul>';
mysqli_close($conn);
}

Iterating values fetched from mysqli

So I am creating a dynamic menu. Where I have stored the main categories of the menu in a separate table and subcategories in another table.
They are stored in this way
Categories Table
id cat_name
1 HOME,
2 PRODUCTS,
3 SOLUTIONS,
4 NEWS & GALLERY,
5 DOWNLOADS,
6 CONTACT
Right Now I am running a query
$sql="SELECT * FROM categories";
$query = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($query)) {
$row['cat_name'];
$cat=explode(",",$row['cat_name']);
}
Then wherever needed I am printing the values like this
<?php echo $cat[0]; .. echo $cat[1]; //and so on ?>
It looks like this right now. And it is supposed to look likethis
But the problem with this solution is that I have to define the index of the array to print it.
I am developing the admin panel for this one and I want that if the admin adds a new menu item then it should automatically fetch it and display it.
But with this solution it is not possible.
I am thinking of iterating the values with a for loop but cannot get it right.
Use foreach ($query as $rows)
or
Use for ($i=0; $i < count($query); $i++)
Probably You can try this also
$sql="SELECT * FROM categories";
$query = mysqli_query($con, $sql);
while($row = mysqli_fetch_assoc($query))
{
$row['cat_name'];
$cat=explode(",",$row['cat_name']);
foreach($cat as $catss)
{
$cat = trim($catss);
$categories .= "<category>" . $cat . "</category>\n";
}
}
You can try this way may be you wish like this for dynamic menu:
$sql="SELECT * FROM categories";
$query = mysqli_query($con, $sql);
$menu = '';
$menu .= '<ul>';
while($row = mysqli_fetch_assoc($query))
{
$menu .= '<li>' . $row['cat_name'] . '</li>';
}
$menu .= '</ul>';
echo $menu;
When you are fetching data from table then you can directly print that value using field name. if you want to further use that so, you have to add in one array like:
$cat[] = $row['cat_name'];
then you can use this value in that manner using for or while:
foreach ($cat as $value) {
echo $value;
}
echo '<ul>';
foreach ($cat as $val) {
echo "<li>{$val}</li>";
}
echo '</ul>';
Instead of the index. Also this should be faster and readable than for loop.
You can save it in array then later access the values.
$sql="SELECT * FROM categories";
$query = mysqli_query($con, $sql);
$cat = array();
while($row = mysqli_fetch_assoc($query)) {
$cat[]=$row['cat_name']
}
Now:
foreach ($cat as $category) {
$cate_gory = explode("," , $category);
foreach ($cate_gory as $categories) {
echo $categories . "<br>";
}
}
Foreach Loop
foreach($cats as $cat)
{
echo $cat;
}
Basic For Loop
for ($i=0; $i<count($cats); $i++)
{
echo $cats[$i];
}
Simple Use Case
<?php
$cats = 'Stack overflow PHP questions';
$cats = explode(' ',$cats);
$html = '<ul>';
foreach($cats as $cat)
{
$html .= '<li>' . $cat . '</li>';
}
$html .= '</ul>';
echo $html;
?>
Your Code
In this case the while loop you are using will iterate over all the values returned from the sql statement, so there is no need to add more complexity. I would remove the commas from the field names and echo out the html this way.
$sql="SELECT * FROM categories";
$query = mysqli_query($con, $sql);
$html = '<ul>';
while($row = mysqli_fetch_assoc($query)) {
$html .= '<li>' . $row['cat_name'] . '</li>';
}
$html .= '</ul>';
echo $html;
?>

How to avoid repetition of one of several items in array (category name)

I know there are similar questions here and I have read some of the posts and answers, experimented with some of them, but whether it is my limited knowledge of PHP or the peculiarity of my case, I need to ask this.
I am building a dictionary (id, english, bulgarian, theme_id) and would like to group the search results according to theme_id. I am using ORDER BY theme_id, id in my query but I end up displaying the theme with each of the results, while I would like to categorize them as follows:
THEME 1
- result 1
- result 2
THEME 2
- result 3
- result 4
.....
Here is the relevant part of my code:
while($row = mysql_fetch_array($result)) {
//$id = $row['id'];
$english = $row['english'];
$bulgarian = $row['bulgarian'];
$theme_id = $row['theme_id'];
$theme_name = "theme_".$lang;
$theme_query= mysql_query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = mysql_fetch_array($theme_query);
$theme = $theme_row[$theme_name];
if($source == "english") {
foreach($keywords as $keyword) {
$english = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223\">".$keyword."</span>", $english);
}
$print .= "<li class=\"results-row\">".$theme.": ".$english." = ".$bulgarian."</li>";
}
elseif($source == "bulgarian") {
foreach($keywords as $keyword) {
$bulgarian = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223;\">".$keyword."</span>", $bulgarian);
}
$print .= "<li class=\"results-row\">".$theme.": ".$bulgarian." = ".$english."</li>";
}
}//end while
EDIT: SOLVED, a friend has helped improve my code.
while($row = mysql_fetch_array($result)) {
$english = $row['english'];
$bulgarian = $row['bulgarian'];
$theme_id = $row['theme_id'];
$theme_name = "theme_".$lang;
$theme_query= mysql_query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = mysql_fetch_array($theme_query);
$theme = $theme_row[$theme_name];
// add all results to an array
$results[] = array(
'english' => $english,
'bulgarian' => $bulgarian,
'theme' => $theme
);
}//end while
$theme = null;
foreach ($results as $result) {
if ($theme != $result['theme']) {
$theme = $result['theme'];
$print .= "<h3>" . $result['theme'] . "</h3>";
}
if ($source == "english") {
foreach ($keywords as $keyword) {
$result['english'] = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223\">" . $keyword . "</span>", $result['english']);
}
$print .= "<li class=\"results-row\">" . $result['english'] . " = " . $result['bulgarian'] . "</li>";
} elseif ($source == "bulgarian") {
foreach ($keywords as $keyword) {
$result['bulgarian'] = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223;\">" . $keyword . "</span>", $result['bulgarian']);
}
$print .= "<li class=\"results-row\">" . $result['bulgarian'] . " = " . $result['english'] . "</li>";
}
}
Based on your code, you should first add all items to an array and afterwards print that array in a separate function/block.
Right after your second MySQL query, put something like
$output[$theme_id] = mysql_fetch_array( $theme_query );
and move all the following code out of the outer result-while-loop (while($row = mysql_fetch_array($result))).
But in fact I would try to put a MySQL query together, to have an ordered, grouped result with all the selected themes in all languages and without querying the database inside a loop.
Or you use something existing, for example this singleton Lexicon class.

How can I produce more than one result in sql ?

The following is a query from which I have taken the result.But right now only one result is printing. I have more than one result in the database.. what should i do in order to print more than one result in header tag
<?php
$sqlcategories = $ilance->db->query("SELECT q.title_spa FROM " . DB_PREFIX . "categories q LEFT
JOIN " . DB_PREFIX . "profile_categories a ON (q.cid = a.cid)
WHERE a.user_id = '" . $res_vendor['user_id'] . "'");
if ($ilance->db->num_rows($sqlcategories) > 0)
{
while ($rows = $ilance->db->fetch_array($sqlcategories))
{
$categories='<h3>'.$rows['title_spa'].'</h3>';
}
}
?>
You probably want to change this line:
$categories = '<h3>'.$rows['title_spa'].'</h3>';
to for example:
$categories .= '<h3>'.$rows['title_spa'].'</h3>';
do like this... append string with .= operator
while ($rows = $ilance->db->fetch_array($sqlcategories))
{
$categories .='<h3>'.$rows['title_spa'].'</h3>';
}
echo $categories;
OR need to store in array then
while ($rows = $ilance->db->fetch_array($sqlcategories))
{
$categories[] ='<h3>'.$rows['title_spa'].'</h3>';
}
printr($categories);
thanks
Before your query write:
$categories = "";
And then in while operator use concatenation (note the dot . before = operator)
$categories .= '<h3>'.$rows['title_spa'].'</h3>';
After that print $categories variable
echo $categories;
$categories='';
while ($rows = $ilance->db->fetch_array($sqlcategories))
{
$categories.='<h3>'.$rows['title_spa'].'</h3>';
}
$categories = '<h3>';
while ($rows = $ilance->db->fetch_array($sqlcategories))
{
$categories .= $rows['title_spa'];
}
$categories .= '</h3>';

Recursive menu with product count

I want to create a recursive menu with the product totals included, however I am stuck now because I already rendered the Topmenu however i cant find another way to do it.
I dont want to use alot of MySQL Queries because it can make my site very slow.
The code i am using:
require 'db.php';
$result = mysql_query("SELECT COUNT(c.category_id) AS count, c. category_id, c.parent_id, cd.name, p.product_id FROM category c
LEFT JOIN category_description AS cd ON (cd.category_id=c.category_id)
LEFT JOIN product_to_category AS ptc ON (ptc.category_id=c.category_id)
LEFT JOIN product AS P ON (p.product_id=ptc.product_id)
GROUP BY c.category_id
ORDER BY c.parent_id,cd.name") or die (mysql_error());
$menuData = array( 'items' => array(), 'parents' => array() );
while ($menuItem = mysql_fetch_assoc($result)) {
$menuData['items'][$menuItem['category_id']] = $menuItem;
$menuData['parents'][$menuItem['parent_id']][] = $menuItem['category_id'];
}
function buildMenu($parentId, $menuData) {
$html = '';
if (isset($menuData['parents'][$parentId]))
{
$html = '<ul>';
foreach ($menuData['parents'][$parentId] as $itemId) {
$iCount = ($menuData['items'][$itemId]['product_id'] != NULL) ? $menuData['items'][$itemId]['count'] : '0';
$html .= '<li>' . $menuData['items'][$itemId]['name'] . ' (' . $iCount . ') ';
$html .= buildMenu($itemId, $menuData);
$html .= '</li>';
}
$html .= '</ul>';
}
return $html;
}
echo buildMenu(0, $menuData);
The expected output:
Dell (1)
--Computer(1)
---DataCable(1)
----Extra Sub (0)
Current output:
Dell (0)
--Computer(0)
---DataCable(1)
----Extra Sub (0)
I think your query returns wrong result. Use
print '<pre>';print_r($menuData);print '</pre>'; before calling buildMenu() function and see whether query returns right data or not.
I think this should get you closer to the right direction:
foreach ($menuData['parents'][$parentId] as $itemId) {
$menu = buildMenu($itemId, $menuData);
$item = $menuData['items'][$itemId];
$iCount = ($item['product_id'] != NULL) ? $item['count'] : '0';
$menuData['items'][$parentId]['count'] += $iCount;
$html .= '<li>' . $item['name'] . ' (' . $iCount . ') ';
$html .= $menu
$html .= '</li>';
}
By re-ordering and then adding the current item's count to the parent item's count, you can make sure that when you output iCount, it will include all of the children's counts as well.
I also used a temporary variable for $menuData['items'][$itemId]. Because you're only doing three array lookups on that $menuData, it might not be substantially more efficient, but it is much easier to read.

Categories