i have mysql table (exe_categories)
| id, title, parent_id, extension |
`<ul>
<li>Parentcat</li>
<ul>
<li>ParentSub</li>
<li>ParentSub</li>
<li>ParentSub</li>
</ul>
<li>Parentcat</li>
<ul>
<li>ParentSub</li>
<li>ParentSub</li>
<li>ParentSub</li>
</ul>
</ul>`
and i want to show a nested category list and subcategory using 2 arguments
first-argument is (parent_id) (0)
AND second argument is (extension) 'com_extension'
I want to show up the nested categories titles and path for the 2 arguments above
i have used this code below and works fine but i cant have another argument for extension argument.
<?php
function query($parent_id) { //function to run a query
$query = mysql_query ( "SELECT * FROM exe_categories WHERE parent_id=$parent_id");
return $query;
}
function has_child($query) { //This function checks if the menus has childs or not
$rows = mysql_num_rows ( $query );
if ($rows > 0) {
return true;
} else {
return false;
}
}
function fetch_menu($query) {
while ( $result = mysql_fetch_array ( $query ) ) {
$id = $result ['id'];
$extension = $result['com_bids'];
$title = $result ['title'];
$menu_link = $result ['menu_link'];
echo "<li><a href='{$menu_link}'><span>{$title}</span></a>";
if (has_child ( query ( $id ) )) {
echo "<div>";
echo '<ul role="menu" class="fofc">';
fetch_menu ( query ( $id) );
echo "</ul>";
echo "</div>";
}
echo "</li>";
}
}
fetch_menu (query(1)); //call this function with 1 parent id
?>
the code above will fetch list of categories starting from parent_id=0 which works great only that i cant have another rule for my extension column .
any help will be appreciated :)
The Html output is like this
Parentcat
ParentSub
ParentSub
ParentSub
Parentcat
ParentSub
ParentSub
ParentSub
Related
I am relatively new to php. I have a function to get all subjects by tableName. I also have a function where I am trying to get all pages where the subject_id (from pages table) matches the subject tables id.
Here are the error's and output:
PDOStatement Object ( [queryString] => SELECT * FROM subjects ORDER BY id ASC )
Array ( [0] => Array ( [id] => 1 [0] => 1 [menu_name] => About Us [1] => About Us [position] => 1 [2] => 1 [visible] => 1 [3] => 1 ) [1] => Array ( [id] => 2 [0] => 2 [menu_name] => Products [1] => Products [position] => 2 etc etc...
Notice: Undefined index: id in /Users/aaronhappe/Sites/php/CMS/includes/db.php on line 39
Fatal error: Call to a member function rowCount() on a non-object in /Users/aaronhappe/Sites/php/CMS/includes/db.php on line 41
And here is the code:
<?php
// controller file
include '../admin-head-includes.php';
$subjects = getAll('subjects', $conn);
$subjectId = $subjects->fetchAll();
print_r($subjects);
echo "<br>";
echo "<br>";
print_r($subjectId);
$pages = getAllLinkedId('pages', $subjectId, $conn);
view('manage-content', array(
'subjects' => $subjects,
'pages' => $pages,
));
// from my db functions file
function getAllLinkedId($tableName, $tableName2, $conn) {
try {
$result = $conn->query("SELECT * FROM $tableName WHERE subject_id = {$tableName2['id']} ORDER BY id ASC");
return ($result->rowCount() > 0)
? $result
: false;
} catch (Exception $e) {
return false;
}
<!-- standard functions file -->
<?php function view($path, $data = null) {
if ($data) {
extract($data);
}
$path = $path . '.views.php';
include "views/$path";
}?>
If I pass $subjects[0] into my getAllLinkedId function, it solves the problem of the Array wrapping other arrays. However, what I am wanting is to spit out, for each subject, the corresponding page. Not just the pages which correspond to one single subject, but which respond to all subjects.
This is my view:
<div class="subjects">
<ul>
<?php
foreach ($subjects as $subject) {?>
<li>
<?=$subject['menu_name'];?>
</li>
<ul>
<?php foreach ($pages as $page) {?>
<?=$page['menu_name']?>
<?php }?>
</ul>
<?php }?>
</ul>
</div>
First problem:
Notice: Undefined index: id in ...
the index id in array $tableName2 is not set, check if is set
Second problem:
Fatal error: Call to a member function rowCount() on a non-object ..
$conn->query() on fails return a non-object, check if $result is a object
In your code:
function getAllLinkedId($tableName, $tableName2, $conn) {
// check if index id is set
if( !isset($tableName2['id']) )
return false;
try {
$result = $conn->query("SELECT * FROM $tableName WHERE subject_id = {$tableName2['id']} ORDER BY id ASC");
// check if $result is object
if( !is_object($result) )
return false;
return ($result->rowCount() > 0) ? $result : false;
} catch (Exception $e) {
return false;
}
}
I was way off base on this. But I have figured it out. I am posting my solution to close this.
<?php
// controller file
include '../admin-head-includes.php';
$subjects = getAll('subjects', $conn);
$pages = getAll('pages', $conn);
$subjects = $subjects->fetchAll();
$pages = $pages->fetchAll();
view('manage-content', array(
'subjects' => $subjects,
'pages' => $pages,
));
<!-- what my view function does -->
<?php function view($path, $data = null) {
if ($data) {
extract($data);
}
$path = $path . '.views.php';
include "views/$path";
}?>
<!-- view -->
<div class="subjects">
<ul>
<?php
foreach ($subjects as $subject) {?>
<li>
<?=$subject['menu_name'];?>
<ul>
<li>
<?php foreach ($pages as $page) {?>
<ul>
<li>
<?php
if ($page['subject_id'] == $subject['id']) {
echo $page['menu_name'];
}
?>
</li>
</ul>
<?php }?>
</li>
</ul>
<?php }?>
</li>
</div>
</ul>
I want to get category name for news post. I can easily get category id but I want to get category name using category Id or other method. How should I do that?
This is how I displayed my blog post in controller
function post($slug = FALSE)
{
if (isset($slug)) {
$data['query'] = $this->mdl_blogs->get_where_slug($slug);
$data['view_file'] = "blog_view";
$this->load->module('template');
$this->template->public_one_col($data);
}
}
in model
function get_where_slug($slug){
$table = $this->get_table();
$this->db->where('news_slug', $slug);
$query=$this->db->get($table);
return $query;
}
in view
<?php
foreach ($query->result() as $row) {
$data['news_title'] = $row->news_title;
$news_body = $row->news_body;
$news_slug = $row->news_slug;
$category_id = $row->category_id;
//$data['category_name'] = $row->category_name;
//$news_category = $row->news_category;
?>
<h2><a href="<?php echo (base_url().'blogs/post/'.$news_slug) ;?>">
<?php echo $data['news_title'];?></a></h2>
<p><?php echo $news_body;?></p>
<p><?php echo $category_id;?></p>
<?php
}
?>
<?php
//echo Modules::run('comments');
?>
Here I also want to display category name. I want to get it from categories table
Here are my tables
in News table
news_id
category_id
news_slug
......
in categories
category_id
category_name
category_slug
You need to join your category table in your model
function get_where_slug($slug){
$table = $this->get_table();
$query=$this->db
->select('n.*,c.category_name,c.category_slug')
->from($table.' n')
->join('category c','n.category_id=c.category_id','LEFT')
->where('n.news_slug', $slug)
->get();
return $query;
}
And in your view you can have you category name in foreach loop as
$category_name = $row->category_name;
same for category_slugif you want this too
I want to create my dropdown menu from a mysql query, but i'm having trouble with the sub-items.
My basic table:
NavigationID ParentID Name Url
1 1 Home home
2 2 About about
3 3 Products products
4 3 Category1 #
5 3 Category2 #
6 4 Product1 #
7 5 Product2 #
My simple MySQL Query and adding to array:
class Navigation{
private $data;
public function __construct($par){
if(is_array($par))
$this->data = $par;
}
public function __toString(){
return '<li>'.$this->data['Name'].'</li>';
}
}
$query = mysql_query("SELECT * FROM Navigation n") or die(mysql_error());
$num = mysql_num_rows($query);
$menuitems = array();
while($row = mysql_fetch_assoc($query)){
$menuitems[] = new Navigation($row);
}
echo '<div id="nav"><ul>';
foreach($menuitems as $item){
echo $item;
}
echo '</ul></div>';
The result of this is:
<div id="nav"><ul>
<li>Home</li>
<li>About</li>
<li>Products</li>
<li>Category1</li>
<li>Category2</li>
<li>Product1</li>
<li>Product2</li>
</ul></div>
But what I would REALLY like is this:
<div id="nav"><ul>
<li>Home</li>
<li>About</li>
<li>Products
<ul>
<li>Category1
<ul>
<li>Product1</li>
</ul>
</li>
<li>Category2
<ul>
<li>Product2</li>
</ul>
</li>
</ul>
</li>
</ul></div>
How can I achieve this result? I've tried many other examples, but none seems to help me. Maybe I'm not searching for the right thing.
Why to make it complicated, this could be done with a very simple recursive function.
This is what I did in my local machine. I have the connection parameter and then called a function
bulit_tree(0);
In this function it will check if the argument is 0 then select all
the item where id and parentid is same.
Then loop through and use the recursive function and generate sub tree.
Need to make sure that the $con is accesible within the function.
$con = mysql_connect("localhost","testuser","testpass");
$db_selected = mysql_select_db('testdb', $con);
if (!$db_selected) {
die ('Can\'t use testdb : ' . mysql_error());
}
bulit_tree(0);
function bulit_tree($pid=0){
global $con ;
if($pid == 0 ){
$qry = "select * from Navigation where NavigationID = ParentID";
$q = mysql_query($qry,$con);
if(mysql_num_rows($q) > 0 ){
echo '<ul>';
while($row = mysql_fetch_assoc($q)){
echo '<li>'.$row["Name"].'';
bulit_tree($row["NavigationID"]);
echo '</li>';
}
echo '</ul>';
}
}else{
$qry = "select * from Navigation where ParentID = ".$pid." AND NavigationID <> ".$pid;
$q = mysql_query($qry,$con);
if(mysql_num_rows($q) > 0 ){
echo '<ul>';
while($row = mysql_fetch_assoc($q)){
echo '<li>'.$row["Name"].'';
bulit_tree($row["NavigationID"]);
echo '</li>';
}
echo '</ul>';
}
}
}
You might need to restructure your DB first. Consider a join table. This comes handy especially if your Product falls into multiple categories.
Master table:
NavigationID Name Url
1 Home home
2 About about
3 Products products
4 Category1 #
5 Category2 #
6 Product1 #
7 Product2 #
Lookup Table:
NavigationID ParentId
1 1
2 2
3 3
4 3
5 3
6 4
7 5
Then in your class, you can make it structured like:
<?php
class Navigation{
private $menuitems;
public function __construct($par){
if(is_array($par))
$this->menuitems = $par;
}
public function __toString() {
$this->printNavigation($this->menuitems);
}
private function printMenuItem($menu) {
echo '<li>'.$menu->name.'';
if(count($menu->children)) {
print printNavigation($menu->children);
}
'</li>';
}
private function printNavigation($menuItems) {
echo "<ul>";
foreach ($menuitems as $menu {
$this->printMenuItem($menu);
}
echo "</ul>";
}
}
class MenuItem{
private $url;
private $name;
private $children;
public function __construct($par){
if(is_array($par)) {
$this->url = $par['url'];
$this->$name = $par['name'];
$this->children = $this->fetchChildren($par['NavigationID']);
}
}
function fetchChildren($id) {
$query = mysql_query("SELECT * from navigation n INNER JOIN Lookup l on l.parentID = n.NavigationID
WHERE n.NavigationID = $id") or die(mysql_error());
$num = mysql_num_rows($query);
if($num > 0) {
while($row = mysql_fetch_assoc($query)){
$this->children[] = new MenuItem($row);
}
}
}
}
$query = mysql_query("SELECT * from navigation n INNER JOIN Lookup l on l.NavigationID = n.NavigationID
WHERE l.NavigationID = l.parentIDn
AND l.NavigationID != n.NavigationID") or die(mysql_error());
$num = mysql_num_rows($query);
$menuitems = array();
while($row = mysql_fetch_assoc($query)){
$menuitems[] = new MenuItem($row);
}
$navigation = new Navigation($menuitems);
echo "<div id='nav'>$navigation</div>";
Thanx for all the comments. I've gone with Agha's suggestion of using a recursive function.
http://crisp.tweakblogs.net/blog/317/formatting-a-multi-level-menu-using-only-one-query.html
In codeigniter 1.73 i'm trying to display books by category. so if i have a category called cars, i should see a list of books within cars. so i tried a nested foreach loop to accomplish this but can't seem to get it to work.
<?php
class Book_model extends Model {
function books_by_category()
{
$this->db->select('*');
$this->db->from('categories');
$this->db->join('books', 'books.category_id = categories.id');
$query = $this->db->get();
return $query->result();
}
}
then in the view:
foreach($data as $category) {
if (sizeof($category['books']))
{
foreach($category['books'] as $book)
{
<li>$book->book_number anchor("book/chapters/$book->id", $book->book_title)</li>
}
} else {
// show 'no books'
}
}
controller:
function index() {
$data = array();
if($query = $this->book_model->books_by_category())
{
$data['books_by_category'] = $query;
foreach($query as $row)
{
if (!isset($data[$row['id']]))
{
$data[$row['id']] = $row;
$data[$row['id']]['books'] = array();
}
$data[$row['id']]['books'][] = $row;
}
$data['main_content'] = 'books_view';
$this->load->view('includes/template', $data);
}
}
Foreach does not have an "else" clause, as you've used.
foreach($category['books'] as $book)
{
// show books
} else {
// show 'no books'
}
Instead, you could do this: (my PHP is rusty)
if(count($category['books']) <= 0)
{
//No books
}
else
{
foreach($category['books'] as $book)
{
//You have books
}
}
A couple of points
function books_by_category()
{
$this->db->select('*');
$this->db->from('categories');
$this->db->join('books', 'books.category_id = categories.id');
$query = $this->db->get();
return $query->result();
}
This code returns all columns for categories and books that have a category set, is this really what you are trying to do? The function name 'books_by_category' would suggest to me that you are only interested in books for one specific category, from looking at your question I'm guessing this isn't the case.
Presuming you are trying to get all books but group them by category I would do the following:
model
function get_books()
{
$this->db->select('*');
$this->db->from('books');
$this->db->join('categories', 'categories.id = books.category_id');
$query = $this->db->get();
if($query->num_rows() == 0)
{
#no books
return false;
}
return $query->result();
}
controller
function index() {
$data = array();
$book_list = $this->book_model->get_books();
if($book_list)
{
$categories = array();
$books_by_category = array();
foreach($book_list as $book)
{
$category_id = $book['category.id'];
$category_name = $book['category.name'];
if(array_key_exists($category_id, $categories))
{
$categories[$category_id] = $category_name;
}
if(array_key_exists($category_id, $books_by_category))
{
$books_by_category[$category_id] = array();
}
$books_by_category[$category_id][] = $book;
}
$data['categories'] = $categories;
$data['books_by_category'] = $books_by_category;
}
$data['main_content'] = 'books_view';
$this->load->view('includes/template', $data);
}
and the view
<?php if(isSet($books_by_category)) : ?>
<?php foreach($books_by_category as $category => $book_list): ?>
<p>Category: <?php echo $categories[$category]; ?></p>
<ul>
<?php foreach($book_list as $book) : ?>
<li><?php echo $book->book_number; ?>. <?php echo anchor('bible/chapters/' . $book->id, $book->book_title); ?></li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
<?php else: ?>
<p>Sorry dude, no books.</p>
<?php endif; ?>
There are a few errors in the code which might be causing this.
You have an extra closing bracket before the end of the foreach loop in your controller.
In your view, you are looping through the books category as $book but then you are trying to work with the $row object inside the loop. Try changing this to $book.
Also in your view, you trying to output some HTML without closing out of your PHP tags. The <li> tags in your code are inside your PHP block and then you try to open up a new PHP block again without ever closing the first one.
I came across this and tried to follow along with the example #mattumotu posted and it was really helpful, but I think it might have some errors - specifically with the way the array is being indexed and then looped through. If you are using a number as an id value, and your ids do not start from zero and increase in numerical order from 0 to x, then you will get unknown index orders in your view when you attempt to loop through the array (at least I did). So I modified the example as follows (note I changed the variable names slightly for my own use):
Model:
public function get_imagery_by_category(){
$this->db->select('extra_imagery.*', FALSE); //MH - not sure what FALSE does here
$this->db->select('extra_image_categories.id as cat_id, extra_image_categories.name as cat_name', FALSE); //MH alias the category id and name as they are the same column names as the imagery name and id
$this->db->from('extra_imagery');
$this->db->join('extra_image_categories', 'extra_image_categories.id = extra_imagery.cat'); //get all images where the image cat matches category id
$this->db->order_by('extra_image_categories.id');
$query = $this->db->get();
if($query->num_rows() == 0){
return false;
} else {
return $query->result_array();
}
}
Here we're just sorting all of our items by the category ID, to ensure we are moving through all of our items in numerical order by their category ID, essentially listing items out by category.
Controller:
$imagery_list = $this->imagery_model->get_imagery_by_category();
if($imagery_list){
$categories = array();
$imagery_by_category = array();
$curCatIndex = -1;
$curCatID = NULL;
foreach($imagery_list as $i=>$image){
$category_id = $image['cat_id'];
$category_name = $image['cat_name'];
if ($curCatID != $category_id){
$curCatIndex+=1;
$categories[$curCatIndex] = $category_name;
$curCatID = $category_id;
}
$imagery_by_category[$curCatIndex][] = $image;
}
//print_r($imagery_by_category);
$data['categories'] = $categories;
$data['imagery_by_category'] = $imagery_by_category;
}
Here we're setting an array to hold our categoriesand an array to hold our items. The $imagery_by_category will be a multidimensional array, such that all items in the first category end up in the first array, all items in the second category are in the second array, etc. Like this:
$imagery_by_category[0][0] = category0, item0
$imagery_by_category[0][1] = category0, item1
$imagery_by_category[1][0] = category1, item0
We're setting a counter ($curCatIndex) that will keep track of each time we hit a new category id, and a variable for the category ID to check if our category id has changed ($curCatID). If we hit a new category ID, we know we've collected all the items for that category, so we increment the curCatIndex counter:
$curCatIndex+=1;
Because our $curCatID starts out as NULL when we begin our loop, we increment the $curCatIndex so that our array will start out at index 0.
Whenever we hit a new category id, we push the name of that category to our $categories array:
$categories[$curCatIndex] = $category_name;
and set the $curCatID equal to our new id:
$curCatID = $category_id;
Then, regardless of whether we are in a new category or not, we push the item to the proper place in the multidimensional array:
$imagery_by_category[$curCatIndex][] = $image;
and lastly we just make these arrays available to our view:
$data['categories'] = $categories;
$data['imagery_by_category'] = $imagery_by_category;
Then, in our view:
<?php if(isSet($imagery_by_category)) : ?>
<?php foreach($categories as $i=>$category_item): ?>
<p><?php echo $category_item ?></p>
<?php foreach($imagery_by_category[$i] as $image_item) : ?>
<?php
echo $image_item['id'];
?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php else: ?>
<p>No imagery</p>
<?php endif; ?>
We have a nested loop. The outer loop loops through our categories:
<?php foreach($categories as $i=>$category_item): ?>
Notice that we've added a variable $i to keep track of the loop index (i.e. array index)
Then we print out the name of the category:
<p><?php echo $category_item ?></p>
and then the inner loop loops through the items in that category:
<?php foreach($imagery_by_category[$i] as $image_item) : ?>
Notice we're using the $i variable here to make sure we select the right dimension from our item array.
Then inside this loop you can do whatever you want. Here I'm just printing out the unique id of my item:
echo $image_item['id'];
Probably a more elegant way to do this, but hope it helps someone. I banged my head against the wall on this for awhile. Thanks to mattumotu for getting me on the right track. I've posted a clearer code example here:
http://mikeheavers.com/main/code-item/order_items_in_one_database_table_by_categories_from_another_database_table
function build_list($id=0,$collapsed="") //return an array with the categories ordered by position
{
$RootPos = "";
$this->c_list = array();
if($id != 0){
$this_category = $this->fetch($id);
$positions = explode(">",$this_category['position']);
$RootPos = $positions[0];
}
// lets fetch the root categories
$sql = "SELECT *
FROM ".$this->table_name."
WHERE position RLIKE '^([0-9]+>){1,1}$' AND c_group = '".$this->Group."'
ORDER BY c_name";
$res = mysql_query($sql) or die(trigger_error("<br><storng><u>MySQL Error:</u></strong><br>".mysql_error()."<br><br><storng><u>Query Used:</u></strong><br>".$sql."<br><br><storng><u>Info:</u></strong><br>",E_USER_ERROR));
while($root = mysql_fetch_array($res)){
$root["prefix"] = $this->get_prefix($root['position']);
$this->c_list[$root['id']] = $root;
if($RootPos == $root['id'] AND $id != 0 AND $collapsed != ""){
$this->list_by_id($id);
continue;
}else{
// lets check if there is sub-categories
if($collapsed == "" AND $id==0){
$has_children = $this->has_children($root['position']);
if($has_children == TRUE) $this->get_children($root['position'],0);
}}}
return $this->c_list;
}
// He is the Author of the code...
Categories Class
Author: Shadi Ali
Now I want to just return the Categories and Sub Categories from the above code.
function browse() {
$categories = new categories;
$categories_list = $categories->build_list();
foreach($categories_list as $c)
{
return $c->$id;
}
}
The above code is not working.... can anyone help me out.
Here are two problems with the browse() function:
The return statement is inside the foreach loop. The statement will return one value for one of the items in the $categories-list (at most), and not continue to loop over the rest of the $categories-list.
The $id variable is never declared or initialised in return $c->$id, perhaps you meant to use $c['id'] or $c->id