Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

best method for creating a data list with nested categories


Go to End


8 Posts   6626 Views

Avatar
ayyurek

Community Member, 41 Posts

21 July 2009 at 9:04am

Hi to everyone. I am very new to Silverstripe, just two days ago installed and spent some hours to understand the general structure. I fell in love and decided to get the risk and use SS in a live project. I built my theme, some custom page types, navigation etc. without any problem and with 10 times less learning effort when I compare with the learning curve of other CMS applications previously I used.

Now my next task is building a section to list the member companies of an association. But I am little bit confused about what is the best way to do this. I will be very glad if anyone can advise me the ideal way for this.

In my data list, every company has some basic data like (company name, address, phone number etc.) And every company is related to one or more categories, and the categories are nested, as below.

-CAT A
-- cat A-1
-- cat A-2
-CAT B
-- cat B-1
-- cat B-2
-CAT C

If a company is member of CAT A-1, it should be listed under CAT A-1 and also CAT-A.

First I thought to make separate nested pages for every category. But then it seems like it's not possible to filter the list to show companies which is member of CAT A and CAT C together, or just to list all the pages.

Is it better to use ComplexTableField or maybe TreeMultiselectField? Or do you have any other suggestion?

Thank you very much for reading this post.

Avatar
Willr

Forum Moderator, 5523 Posts

21 July 2009 at 7:32pm

Edited: 21/07/2009 7:32pm

every company is related to one or more categories

This would be a many_many relation. A company has many categories and a category has multiple companies. See this tutorial for more info on managing relationships - http://doc.silverstripe.com/doku.php?id=tutorial:5-dataobject-relationship-management. You could use the TableListField (or ComplexTableField) or another way to manage many_many is to use a CheckboxSet Field http://doc.silverstripe.com/doku.php?id=checkboxsetfield

Avatar
ayyurek

Community Member, 41 Posts

22 July 2009 at 4:16am

Thank you very much Will. But what about nested categories? I think with TableListField (or ComplexTableField) it's not so easy to create nested categories. Or is it OK to add a parent category field with a select list control to allow for selecting a parent category when adding a new category.

I also think about a structure like this:

Categories extends Page.
Tab within Categories:
Companies extends DataObject.

In this way I think it's not possible to manage how to add one company to a multiple category.

Thank you

Avatar
motoservo

Community Member, 27 Posts

22 July 2009 at 3:54pm

Edited: 22/07/2009 3:55pm

Would a self join, something like this, work for you?

class Category extends DataObject {

static $has_one = array(
'Parent' => 'Category'
);

static $has_many = array(
'Children' => 'Category'
);

Avatar
ayyurek

Community Member, 41 Posts

14 August 2009 at 12:07am

Thank you very much for all answers. I am still trying different methods and soon will find the best one fits to this. As soon as I get a result, I will share the solution here with other forum readers.

Avatar
ayyurek

Community Member, 41 Posts

5 October 2009 at 10:57am

Thank you very much for all! Motoservo, thanks a lot for the suggestion, I used exactly your code. Here is what i did for other people who will need this in the future.

class Section extends DataObject {
	
	static $db = array(
		'Name' => 'Varchar'
	);
	   
	static $has_one = array(
   'Parent' => 'Section'
    );

    static $has_many = array(
   'Children' => 'Section'
    );
	
	static $belongs_many_many = array(
		'Companies' => 'Company'
	);
	
	function getCMSFields_forPopup() {
		$fields = new FieldSet();
		$fields->push( new TextField( 'Name' ) );
		return $fields;
	}
	
}

And then I create a nested tree of categories in the frontend with this code.

function Sections() {
  $rootLevel = DataObject::get("Section", "ParentID = 0", "ID ASC"); // sections at the root level only
  $output = "";
  $output = $this->makeList($rootLevel);
  return $output;
 }
 
  private function makeList($sections) {
  $output = "";
  if(count($sections)) {
    $output = '
    <ul class="treeo">';
   foreach($sections as $section) {
    
     $output .= '
      <li><a href="member-companies/id/'.$section->ID.'" title="">'.$section->Name.'</a>';
     $whereStatement = "ParentID = ".$section->ID;
     //$childPages = new DataObjectSet();
     $childPages = DataObject::get("Section", $whereStatement);
     $output .= $this->makeList($childPages);
     $output .= '
      </li>';
   
   }
   $output .= '
    </ul>';
  }
  return $output;
 }

And after this, I put this to my template as

$Sections

I am using model admin in the backend to manage categories and companies. If someone need it, just write here please and I will post all the related code.

Regards

Avatar
briley

Community Member, 7 Posts

16 January 2010 at 10:19am

We're dealing with a very similar issue ayyurek, and I'd like to see how you're handling the nested categories on the back-end?

Avatar
ayyurek

Community Member, 41 Posts

18 January 2010 at 10:56pm

Edited: 18/01/2010 10:56pm

Hello Briley,

I used it for managing contacts with ModelAdmin. First download the extension and install. You can find some examples
here.

Basically, under mysite/code create a page ContactManager.php

class ContactManager extends ModelAdmin {
   
  public static $managed_models = array(   //since 2.3.2
      'Contact',
      'Category'
   );
 
  static $url_segment = 'contacts'; // will be linked as /admin/contacts
  static $menu_title = 'Contact Manager';
 
}

After this, create class for Category. ( create Category.php under mysite/code )

class Category extends DataObject {
   
   static $db = array(
      'Name' => 'Varchar'
   );
   
   static $has_one = array(
'Parent' => 'Category'
);

static $has_many = array(
'Children' => 'Category'
);
   
   static $belongs_many_many = array(
      'Contacts' => 'Contact'
   );
   
   function getCMSFields_forPopup() {
      $fields = new FieldSet();
      $fields->push( new TextField( 'Name' ) );
      return $fields;
   }
   
}

Then do the same for Contact. (create Contact.php under mysite/code )
class Contact extends DataObject {
   
   static $db = array(
      'Name' => 'Varchar'
   );
   
   static $has_one = array(
'Parent' => 'Category'
);
   
   
   function getCMSFields_forPopup() {
      $fields = new FieldSet();
      $fields->push( new TextField( 'Name' ) );
      return $fields;
   }
   
}

Run - yoursiteurl/dev/build/
and you are ready.
I hope it will help you.
You can also download some example code here
Regards