tree menu php mysql list - php

I am trying to build an un-oredered list menu tree from my database in PHP and MySQL from here
I have an array of page objects I am returning from the db. Each page object has parent_id attribute, which is set to null if it doesn't have a parent. Here's what the page objects look like:
mydatabase
PHP Handling
$menu = mysqli_query($conn, "SELECT * FROM kategori ORDER BY id_kategori DESC");
while($row=mysqli_fetch_assoc($menu)) {
}
function has_children($rows,$id) {
foreach ($rows as $row) {
if ($row['parent'] == $id)
return true;
}
return false;
}
function build_menu($rows,$parent=0)
{
$result = "<ul>";
foreach ($rows as $row)
{
if ($row['parent'] == $parent){
$result.= "<li>{$row['nama_kategori']}";
if (has_children($rows,$row['id_kategori']))
$result.= build_menu($rows,$row['id_kategori']);
$result.= "</li>";
}
}
$result.= "</ul>";
return $result;
}
echo build_menu($menu);
This isn't outputting the correct results for me, can anyone help me

Related

Can't get to show all of a tree in a traversal preorder in php

I have a table in my database that host many genealogy trees.
-----------------------------
- id name parent_id
-----------------------------
- 1 grandfather NULL
- 2 father 1
- 3 uncle 1
- 4 son 2
- 5 brother 2
- 6 cousin's dauther 7
- 7 cousin 8
- 8 auntie 1
The problem is I can't get to show all the names because of an edge case:
-When I have a person with a parent_id that is bigger than it's parent's parent_id
(see cousin's daugter)
I use this queries to get the table:
$sql = "SELECT p1.id, p1.name, p1.parent_id FROM pariente p1
ORDER BY p1.parent_id";
$result = $conn->query($sql);
The problem is that if I use "ORDER BY parent_id" "cousin's dauther" won't show and if I use "ORDER BY id" "cousin" won't show.
I use this functions to make a the tree into an array and draw it:
function make_tree($data, $root) {
$tree = [];
foreach ($data as $node) {
insert($tree, $node);
}
return $tree;
}
function insert(&$root, &$node) {
if (!$root) {
$root = $node;
}
else if ($root["id"] === $node["parent_id"]) {
$root["children"][] = $node;
}
else if (array_key_exists("children", $root)) {
foreach ($root["children"] as &$c) {
if (insert($c, $node)) {
break;
}
}
}
}
function preorder2(&$root) {
if ($root) {
echo "<li>";
echo $root["name"];
if (array_key_exists("children", $root)) {
echo "<ul>";
foreach ($root["children"] as $c) {
preorder2($c);
}
echo "</ul>";
}
echo "</li>";
}
}
?>
And after I use this to call the functions:
<div>
<?php
while( $row = mysqli_fetch_assoc( $result)){
$resguard[] = $row;
}
$tree = make_tree($resguard);
preorder2($tree);
?>
</div>
I had a similar problem once, and here's how I fixed it.
Iterate over the dataset, putting each node in your array, and keep track of what you want to be your root node.
Iterate over the array. For each node where the parent_id is not null, lookup the parent node by id, and add the current node as a child. There's no need to use recursion when building the tree.
At the end I believe I didn't get toastifier answer, but it get me thinking and I ended up solving the problem (still using the way ggorlen shows the tree).
First this are the queries:
$sql = "SELECT p1.id, p2.name, p2.id as minor, p2.name FROM pariente p1 INNER JOIN pariente p2 ON p1.id = p2.parent_id ORDER BY p1.id";
$result = $conn->query($sql);
$sql2 = "SELECT p1.id, p1.nombre, p1.padre_id FROM pariente p1 WHERE p1.padre_id IS NULL ORDER BY p1.id";
$raices = $conn->query($sql2);
The functions:
function make_tree($resguardo, $root){
$tree = [];
$tree = $root;
foreach ($resguardo[$root["id"]] as $node) {
add($tree, $node, $resguardo);
}
return $tree;
}
function add(&$root, &$children, $resguardo){
$root["children"][$children["minor"]] = $children;
$flag= false;
if (isset($resguardo[$children["minor"]])) {
$flag = true;
}
if ($flag == false){
return;
} else {
foreach ($resguardo[$children["minor"]] as $child) {
agregar($root["children"][$children["minor"]], $child, $resguardo);
}
}
}
function preorder2(&$root) {
if ($root) {
echo "<li>";
echo '<a href="">';
echo $root["name"];
echo "</a>";
if (array_key_exists("children", $root)) {
echo "<ul>";
foreach ($root["children"] as $c) {
preorder2($c);
}
echo "</ul>";
}
echo "</li>";
}
}
And I call them here:
while( $row = mysqli_fetch_assoc($result)){
$resguardo[$row["id"]][] = $row;
}
while( $root = mysqli_fetch_assoc( $roots)){
echo '<ul>';
$tree = make_tree($resguardo, $root);
preorder2($tree);
echo "</ul>";
}
Thanks alot to both of you, I would never solve it without your help.

arrange category and subcategory in php and Codeigniter

Here I have my database table and my table name is category where I store my data category and subcategory in category column
i want to fetch this data like this format in ul li for this code i have trying to arrange but i am not fetch data perfectly like this please help me to arrange my code this format.
You can try like this
//to select categories
$this ->db-> select();
$this->db->from('category');
$this->db->where('pid',0);
$query = $this->db->get();
$categories = array();
$i=0;
foreach ($query->result_array() as $row) {
//put all category names to $categories array
$categories[$i] =$row['category'];
$i++;
}
//to select relevant sub categories
$sub_categories=array();
foreach ($categories as $category) {
$this ->db-> select();
$this->db->from('category');
$this->db->like('category', $category, 'after');
$query = $this->db->get();
$j=0;
foreach ($query->result_array() as $row) {
//put all sub categories names to $sub_categories array
$sub_categories[$category][$j] =$row['category'];
$j++;
}
}
$return_data['categories']=$categories;
$return_data['sub_categories']=$sub_categories;
return $return_data;
This code is useful for get nth level of category,subcategory array
controller:
$this->load->model('getmenu_model');
function get_menu() {
$ci = & get_instance();
$ci->load->model("getmenu_model");
$menu['menu'] = $ci->getmenu_model->get_menu();
$echo = echoMenu($menu['menu']);
//$echo.= "<li>Loose Diamonds</li>";
$menu['print_menu']=$echo;
print_r($menu);
//return $menu;
}
function echoMenu($arr) {
$ci = & get_instance();
$echo = "";
//$echo.="<ul>";
foreach ($arr as $subArr) {
if (!empty($subArr['sub_menu'])) {
$echo.= "<li>";
$echo.= "" . $subArr['name'] . "";
if ($subArr['sub_menu']) {
$echo.= "<ul>";
$echo .=echoMenu($subArr['sub_menu']);
$echo.= "</ul>";
}
$echo.= "</li>";
} else {
$echo.= "<li>" . $subArr['name'] . "</li>";
}
}
//$echo.= "</ul>";
return $echo;
}
model:
public function get_menu() {
$this->db->select('id,name,parent_id');
$menu = $this->db->get('category')->result_array();
$data=$this->menu_child($menu);
//print_r($data);
return $data;
}
function menu_child($menu, $parent = NULL) {
// echo $parent."---";
$main_menu = array_filter($menu, function($a)use($parent) {
return $a['parent_id'] == $parent;
});
// print_r($main_menu);
if ($main_menu) {
foreach ($main_menu as $key => $value) {
$main_menu[$key]['sub_menu'] = $this->menu_child($menu, $value['id']);
}
}
// print_r($main_menu);
return $main_menu;
}

how to handle php forloop returning no results

Im running a for loop to gather data from a forum table, but im not quite sure what to do to make it handle if there are no results returned. Here is the code i have to gather the data.
$q = $this->db->query("SELECT * FROM newslist ORDER BY pubdate DESC");
if ($q->num_rows() > 0) {
foreach ($q->result() as $row) {
$data[] = $row;
}
}
return $data; else {
return echo = "nose";
}
$q = $this->db->query("SELECT * FROM newslist ORDER BY pubdate DESC");
$data = array(); // Initialize the array in case there are no records.
if ($q->num_rows() > 0){
foreach ($q->result() as $row){
$data[] = $row;
}
}
if (empty($data)) { // If there are no records, $data will be empty.
return "nose";
}
else { // If $data has records, will return data from SQL.
return $data;
}
Explanation:
1) Initialize the $data variable. If we do not get any records, $data will not be appended, causing initialized variable $data return error. By initializing it before loop, we are overcoming it.
2) Check empty() ness of $data, if its empty, return error string, else $data.
Little bit of a flow issue. See revised solution.
$q = $this->db->query("SELECT * FROM newslist ORDER BY pubdate DESC");
if($q->num_rows() > 0){
foreach($q->result() as $row){
$data[] = $row;
}
return $data;
} //<-- this was on the wrong line
else {
return "No data!";
}
Return your data inside if condition and don't use return and echo at same time.
$q = $this->db->query("SELECT * FROM newslist ORDER BY pubdate DESC");
if ($q->num_rows() > 0) {
foreach ($q->result() as $row) {
$data[] = $row;
}
return $data;// return data inside if condition
}
else {
return "nose";// remove echo from here
}
Simply You can use this
$query = $this->db->query("SELECT * FROM newslist ORDER BY pubdate DESC");
$result = $query->result_array();
$count = count($result);// counting data
if(empty($count))
{
$log = 'nose';
return $log;
}
else
{
return $result;
}

Codeigniter select distinct and passing the list of variables

Just want to SELECT DISTINCT country FROM table WHERE user_id=$user_id, pass the country list from model to controller and then pass the JSON representation of the country list but as I am a newbie in Codeigniter I am not sure if wrote the query correctly and if I return the list or a single value. Could you please check my code.
Model:
public function did_get_country_list($user_id) {
$this->db->distinct('country');
$this->db->where('user_id',$user_id);
$query = $this->db->get('table');
if ($query->num_rows() >= 1) {
foreach ($query->result() as $row)
{
$country = $row->country;
}
return $country;
}
else{
return false;
}
}
Controller:
$country = $this->model_users->did_get_country_plans($user_id);
echo json_encode($country);
Your code looks almost ok to me, but I think you should change 2 lines:
1) Remove the check for num_rows before the actual query.
2) To return an array of countries, add [] at the end of $country to push the new values.
So, instead of this snippet:
if ($query->num_rows() >= 1) {
foreach ($query->result() as $row)
{
$country = $row->country;
}
return $country;
}
else{
return false;
}
You would have:
$country = false;
foreach ($query->result() as $row)
{
$country[] = $row->country;
}
return $country;

PHP Multidimensional object menu

I have made function to get multidemnsional menu from database.
public function get_menu($parent=0,$vis=1) {
$categories = array();
$this->db->from('ci_categories');
$this->db->where('cat_child',$parent);
$this->db->where('cat_vis',1);
$this->db->order_by('cat_order');
$q = $this->db->get();
$result = $q->result();
$i=0;
foreach($result as $mainCategory) {
$mainCategory->cat_subcategories = $this->get_menu($mainCategory->cat_id);
$categories[$i] = $mainCategory;
$i++;
}
return $categories;
}
It is working but I would like to print out the menus. For now I can print main menu and one child with this code:
if (count($menu) > 0) {
foreach($menu as $menu_item) {
$link = anchor("category/".$menu_item->cat_url, $menu_item->cat_name);
echo "<li>$link";
if (!empty($menu_item->cat_subcategories)) {
echo "<ul>";
foreach($menu_item->cat_subcategories as $subcat) {
$sub_link = anchor("category/".$subcat->cat_url, $subcat->cat_name);
echo "<li>$sub_link</li>";
}
echo "</ul>";
}
echo "</li>";
}
}
It is working too but how could I print out even 3rd or 4th submenu without manualy writing those foreach and ifs ? Thanks
You can try a recursive function...
Something like:
function showMenu($menu) {
echo "<ul>";
foreach ($menu as $menu_item) {
$link = anchor("category/".$menu_item->cat_url, $menu_item->cat_name);
echo "<li>$link";
if (!empty($menu_item->cat_subcategories)) showMenu($menu_item->cat_subcategories);
echo "</li>";
}
echo "</ul>";
}
That's an idea ;)

Categories