Welcome Guest, Not a member yet? Register   Sign In
Categories, subcategories, items
#1

[eluser]roadie[/eluser]
Hi guys!
I need some help and I'd really appreciate it.

I'd like to create an application, something like a business directory, but not very complicated.

The structure is like this:
Category1
Category1-1
Item1
Item2
Item3
Category1-2
Item4
.........
Categroy1-3
Category2
and so on.....

I need some help with the model. I've been trying for few days and I can't figure it out how to do it. I'm new in CI and your help would be really appreciate it.
#2

[eluser]ciGR[/eluser]
Hi, first of all you must set your database structure.

For example you can set the table for categories
like

Code:
cat_id | cat_name | parent_cat_id

for example the Category1-1 has parent_id the cat_id of the category1, also the Category1-2 ...
The top categories like Category1, Category2 you can set parent_id = 0, to separate from the others.


another approach id to create 2 tables in your database
first
Code:
cat_id | cat_name

and a second with
Code:
id | parent_cat_id | sub_cat_id |

for example in the second table you may have

Code:
1 | Category1-id | Category1-1-id
2 | Category1-id | Category1-2-id
3 | Category2-id | Category2-1-id
                .
                .
                .

and work with joins queries.
#3

[eluser]roadie[/eluser]
Hi!
Thanks for your reply.
I'm thinking to create 2 tables anyways, something like this.

1.Category
id
parent_id
name
description

2.Item
id
parent_id
name
content


The Item will have the actual content.
I wrote some simple controller, model and view but I could make it retrieve only the top-level categories.

<<Controller>>
........
function category()
{
$this->load->model('category_model');
$data['cats'] = $this->category_model->getCategory();
$this->load->view('categories_view', $data);

}

<<Model>>
......
function getCategory()
{
$query = $this->db->get_where('category', array('parent_id' => 0));
return $query->result();
}
function getSubcats($id)
{
$query = $this->db->get_where('category', array('parent_id' =>$id));
return $query->result();
}

<<View>>
........
&lt;?php foreach($cats as $cat): ?&gt;
<div>
<h1>&lt;?php echo $cat->name; ?&gt;</h1>
&lt;?php $subcats = $this->category_model->getSubcats($cat->id);?&gt;
<ul>
&lt;?php foreach($subcats as $subcat): ?&gt;
<li>&lt;?php echo anchor('site/category/'.$subcat->id, $subcat->name); ?&gt;</li>
&lt;?php endforeach ?&gt;
</ul>
</div>
&lt;?php endforeach ?&gt;
#4

[eluser]slowgary[/eluser]
Wrap your code in [ code ] tags next time, it makes it easier for people to help.

Calling your model from the view is kind of a no-no. While codeigniter is not overly restrictive and will LET you do so, you should not do so for good, clean, maintainable MVC structure.

Before you can get good help, there are a few questions to ask. Do you ever plan to have more than 2 levels of categories? If you'll only have top-level and second level categories, it will be easier to construct your navigational tree. New question... Will your categories be alphabetized? Also, will you show visitors the entire navigational tree, or will they only see the top level category and need to click on a top level before seeing its subcategories?

I wouldn't create a "get_sub_categories()" method since it implies that you may be doing LOTS of queries per page load just to show visitors the navigation. You're better off getting all the categories in a single query and sorting them out in your controller before passing them to the view.

Assuming alphabetized categories, and also assuming that your tree will be max of 2 levels and entirely visible to the visitor, you could do something like this (pseudocode):

Code:
//model
function get_categories()
{
     return "Get all categories, order by parent_id, name"
}

//controller
function browse()
{
     $unsorted = model->get_categories();
     $sorted = array();
     $count = count($unsorted);

     //sort the categories into a nested tree
     for($i = 0; $i < $count; $i++)
     {
          if(isset($unsorted[$i]))
          {
               if($unsorted[$i]['parent_id'] == 0)
               {
                    $parent_id = $unsorted[$i]['id'];
                    $sorted[] = $unsorted[$i];
                    unset($unsorted[$i]);

                    $x = count($unsorted);
                    for($i2 = 0; $i2 < $x; $i2++)
                    {
                         if($unsorted[$i2]['parent_id'] == $parent_id)
                         {
                              $sorted[] = $unsorted[$i2];
                              unset($unsorted[$i2]);
                         }
                    }
               }
          }
     }

     $data['categories'] = $sorted;

     $this->load->view('categories', $data);
}

//view
<ul>
&lt;?php foreach($categories as $cat): ?&gt;
     &lt;?php if($cat['parent_id'] == 0): ?&gt;
          <li class='parent'><a href='/show_items/&lt;?php echo $cat[' title='&lt;?php echo $cat['>&lt;?php echo $cat['name']; ?&gt;</a></li>
     &lt;?php else: ?&gt;
          <li class='child'><a href='/show_items/&lt;?php echo $cat[' title='&lt;?php echo $cat['>&lt;?php echo $cat['name']; ?&gt;</a></li>
     &lt;?php endif; ?&gt;
&lt;?php endforeach; ?&gt;
</ul>

If you need more than 2 levels of navigation, you'd want to throw some of that code into a function and call it recursively.

I hope this helps.
#5

[eluser]roadie[/eluser]
Thanks slowgary!
I will have only 2 levels of categories which I want to show them from the begining.

Category1
Category1-1
Category1-2
Category1-3

Category2
Category2-1
Category2-2
..............

Then I need another view to show the subcat with it's items. Can I use the same view but just add a condition or I should do another view?

Code:
if cat_has_no_child(){ //the category is a subcat-> all the children are items
$data1 = get_items(); //make a query to retrieve the items for the selected category
$this->load->view('categories', $data1);
}
else{
$data2 = get_categories();
$this->load->view('categories', $data2);
}


Category1-1
Item1
Item2
Item3
......

And then the last view the Item itself.
#6

[eluser]slowgary[/eluser]
Either works... I'm not sure of your exact application, but I'd probably have a view that contains the navigation, a view that shows a list of items, and a view that shows a single item and all of it's details. As far as the actual frontend goes, I'd likely include the navigation view on all the pages... so a user would either see a bunch of categories on the left and a list of items on the right, or they'd see a bunch of categories on the left and one item (detail view) on the right. Throw something into your categories view to add a CSS class to a category if it's currently being viewed and you're good to go.

Good luck.
#7

[eluser]xeroblast[/eluser]
as what i learn in hierarchical data, there are 2 types of model... the adjacent model and the nested model... and it is easier if your so much of the 2...

for more info: check this out: http://dev.mysql.com/tech-resources/arti...-data.html
#8

[eluser]Zeeshan Rasool[/eluser]
You can put child id . parent id so that we can get both ids (child,parent from a single field). Just save in db
1.2
1.3
1.4
etc
#9

[eluser]slowgary[/eluser]
Roadie,
There are different ways to store your categories in the database, as xeroblast mentioned. The method you're using is an adjacency list, but I wouldn't get caught up on that. Stick with what you have, it's simplest and will work well for what you're doing. As far as combining 2 fields into 1 using a period, I wouldn't recommend it. Keeping your data separate and normalizes will be better in the long run. You're on the right track.




Theme © iAndrew 2016 - Forum software by © MyBB